#include "windows.h"
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <fcntl.h>
#include "winatari.h"
#include "graphics.h"
#include "registry.h"
#include "resource.h"
#include "atari.h"
#include "sio.h"
#include "rt-config.h"

extern int global_artif_mode;
extern ULONG	ulScreenMode;
extern int		nStartX, nStartY;
extern ULONG	ulSoundState;
extern int		nSoundRate, nSoundVol;
extern HWND	MainhWnd;
extern char	current_rom[ ];
extern int  ulJoystickSelects;
extern int	nJoyRepeat, nJoySkip;
extern int	cart_type;
extern 	TCHAR	gcErrorString[];

int		ulMiscStates = 0;
ULONG	ulDontShowFlags = 0;
static	int		nVersion = CURRENT_REV;

char *szDriveRegID[MAX_DRIVES] = { REG_DRIVE1, REG_DRIVE2, REG_DRIVE3, REG_DRIVE4, REG_DRIVE5, REG_DRIVE6, REG_DRIVE7, REG_DRIVE8 };
char	szTemplateFile[ MAX_PATH ];
char	szTemplateDescrip[ MAX_PATH ];
char	atari_exe_dir[ MAX_PATH ];
int		iKBTable[256];						/* Number of virtual key codes */

extern BOOL TestRomPaths( void );

int ReadKeyTemplate( char *name )
{
	int	iFile;
	BOOL	bNoError = TRUE;

	iFile = open( name, O_RDONLY | O_BINARY , 0777 );
	if( iFile != -1 )
	{
		unsigned char	cData;
		char	szTag[4];

		szTag[3] = 0;
		if( read( iFile, &szTag, 3 )== -1 )
			bNoError = FALSE;

		if( strcmp( &szTag[0], "A8K" ) )
			MessageBox( NULL, "Not an Atari keyboard template file", "Atari800Win", MB_OK );
		else
		{
			if( (read( iFile, &cData, 1 )== -1) || cData!=KEYBOARD_TEMPLATE_VERSION )
				MessageBox( NULL, "Incorrect/old version of template file", "Atari800Win", MB_OK );
			else
			{
				if( read( iFile, &cData, 1 )== -1 )
					bNoError = FALSE;
				else
				{
					if( read( iFile, szTemplateDescrip, cData)== -1 )
						bNoError = FALSE;
					else
					{
						szTemplateDescrip[cData] = 0;
						if( read( iFile, iKBTable, 256 * sizeof( int ))== -1 )
							bNoError = FALSE;
					}
				}
			}
		}
		close( iFile );

		if( !bNoError )
			strcpy( szTemplateFile, name );
	}
	else
		bNoError = FALSE;

	return bNoError;
}

//DeleteAllRegKeys will recursively delete everything from a supplied initial
//Key. All subkeys are enumerated and deleted as found. Note that ALL values
//underneath a key are deleted when that key is deleted.

void DeleteAllRegKeys( HKEY hkInput, char *name )
{
	HKEY	hkKey;
	DWORD	dwIndex = 0;
	DWORD	dwBufSize = 256;
	char	szSubKeyName[256];
	FILETIME	dummy;

	if( hkInput == NULL )
	{
		if( RegOpenKeyEx(
			HKEY_CURRENT_USER,		// handle of open key 
			REGNAME,				// address of name of subkey to open 
			0,						// reserved 
			KEY_ALL_ACCESS,			// security access mask 
			&hkKey 					// address of handle of open key 
			)!=ERROR_SUCCESS )
		{
			return;
		}
	}
	else
		hkKey = hkInput;

	while( RegEnumKeyEx( 
				hkKey,			// handle of key to enumerate 
				dwIndex++,		// index of subkey to enumerate 
				szSubKeyName,	// address of buffer for subkey name 
				&dwBufSize,		// address for size of subkey buffer 
				NULL,			// reserved 
				NULL,			// address of buffer for class string 
				NULL,			// address for size of class buffer 
				&dummy			// address for time key last written to 
	) == ERROR_SUCCESS )
	{
		DeleteAllRegKeys( hkKey, szSubKeyName);
	}
	RegDeleteKey( HKEY_CURRENT_USER, REGNAME );
}

//*---------------------------------------------------------------------------------
//| WriteRegDWORD writes out an int to the preset Registry key 
//| HKEY_CURRENT_USER\REGNAME. If the HKEY passed in is valid it is used, 
//| otherwise the key is grabbed and released within the function. Note that 
//| RegOpenKey is used here instead of RegCreateKey, which is only used at init time.
//| No calls should be made to this prior to HandleRegistry(). Any write to the 
//| Registry that doesn't work is skipped with user notification
//*---------------------------------------------------------------------------------
void WriteRegDWORD( HKEY hkInput, char *item, DWORD value)
{
	HKEY	hkKey;

	if( hkInput == NULL )
	{
		if( RegOpenKeyEx(
			HKEY_CURRENT_USER,		// handle of open key 
			REGNAME,				// address of name of subkey to open 
			0,						// reserved 
			KEY_WRITE,				// security access mask 
			&hkKey 					// address of handle of open key 
			)!=ERROR_SUCCESS )
		{
			LoadString( NULL, IDS_REG_OPEN_ERROR, gcErrorString, LOADSTRING_STRING_SIZE );
			MessageBox( MainhWnd, gcErrorString, "Atari800Win", MB_ICONSTOP );
			return;
		}
	}
	else
		hkKey = hkInput;
	
	if( RegSetValueEx(
		hkKey,					// handle of key to set value for  
		item,					// address of value to set 
		0,						// reserved 
		REG_DWORD,				// flag for value type 
		(unsigned char *)&value,// address of value data 
		sizeof( DWORD )			// data buffer size
		)!=ERROR_SUCCESS )
	{
		LoadString( NULL, IDS_REG_WRITE_ERROR, gcErrorString, LOADSTRING_STRING_SIZE );
		MessageBox( MainhWnd, gcErrorString, "Atari800Win", MB_ICONSTOP );
	}	
	if( hkInput == NULL )
		RegCloseKey( hkKey );
}

//*---------------------------------------------------------------------------------
//| ReadRegDWORD retrieves an existing value. To make it bulletproof the calling routine can 
//| request to display errors or not, depending on how fatal they are considered
//*---------------------------------------------------------------------------------
int ReadRegDWORD( HKEY hkInput, char *item, DWORD *data, BOOL bShowError )
{
	DWORD type, size, value;
	HKEY	hkKey;
	
	if( hkInput == NULL )
	{
		if( RegOpenKeyEx(
			HKEY_CURRENT_USER,		// handle of open key 
			REGNAME,				// address of name of subkey to open 
			0,						// reserved 
			KEY_READ,				// security access mask 
			&hkKey 					// address of handle of open key 
			)!=ERROR_SUCCESS )
		{
			if( bShowError )
			{
				LoadString( NULL, IDS_REG_OPEN_ERROR, gcErrorString, LOADSTRING_STRING_SIZE );
				MessageBox( MainhWnd, gcErrorString, "Atari800Win", MB_ICONSTOP );
				return READ_REG_FAIL;
			}
		}
	}
	else
		hkKey = hkInput;
	
	//Win95 is really picky about having this size set; WinNT doesn't care. Go figure.
	size = sizeof( DWORD );
	if( RegQueryValueEx(
		hkKey,					// handle of key to query 
		item,					// address of name of value to query 
		0,						// reserved 
		&type,					// address of buffer for value type 
		(unsigned char *)&value,// address of data buffer 
		&size			 		// address of data buffer size 
		)!=ERROR_SUCCESS )
	{
		if( bShowError )
		{
			char	szError[256];
			sprintf( szError, "Error reading the key %s from Registry.\nThis value will be replaced with a default.", item );
			MessageBox( MainhWnd, szError, "Atari800Win", MB_ICONSTOP );
		}
		else
		{
			if( hkInput == NULL )
				RegCloseKey( hkKey );
		}
		if( hkInput == NULL )
			RegCloseKey( hkKey );
		return READ_REG_FAIL;
	}
	
	if( type!=REG_DWORD || size != sizeof( DWORD ) )
	{
		LoadString( NULL, IDS_REG_WRONG_SIZE, gcErrorString, LOADSTRING_STRING_SIZE );
		MessageBox( MainhWnd, gcErrorString, "Atari800Win", MB_ICONSTOP );
		if( hkInput == NULL )
			RegCloseKey( hkKey );
		return READ_REG_FAIL;
	}

	if( hkInput == NULL )
		RegCloseKey( hkKey );
	
	*data = value;
	return TRUE;
}

DWORD ReadRegBinary( HKEY hkInput, char *item, char *buffer, unsigned long maxsize, BOOL bShowError )
{
	DWORD	type;
	HKEY	hkKey;
	unsigned int		iFullSize = maxsize;
	
	if( hkInput == NULL )
	{
		if( RegOpenKeyEx(
			HKEY_CURRENT_USER,		// handle of open key 
			REGNAME,				// address of name of subkey to open 
			0,						// reserved 
			KEY_READ,				// security access mask 
			&hkKey 					// address of handle of open key 
			)!=ERROR_SUCCESS )
		{
			if( bShowError )
			{
				LoadString( NULL, IDS_REG_OPEN_ERROR, gcErrorString, LOADSTRING_STRING_SIZE );
				MessageBox( MainhWnd, gcErrorString, "Atari800Win", MB_ICONSTOP );
				return READ_REG_FAIL;
			}
		}
	}
	else
		hkKey = hkInput;
	
	if( RegQueryValueEx(
		hkKey,					// handle of key to query 
		item,					// address of name of value to query 
		0,						// reserved 
		&type,					// address of buffer for value type 
		(unsigned char *)buffer,// address of data buffer 
		&maxsize			 	// address of data buffer size 
		)!=ERROR_SUCCESS )
	{
		if( bShowError )
		{
			char	szError[LOADSTRING_STRING_SIZE];
			LoadString( NULL, IDS_REG_ERROR_KEY, gcErrorString, LOADSTRING_STRING_SIZE );
			sprintf( szError, gcErrorString, item );
			MessageBox( MainhWnd, szError, "Atari800Win", MB_ICONSTOP );
		}
		else
		{
			if( hkInput == NULL )
				RegCloseKey( hkKey );
			*buffer = 0;
		}
		if( hkInput == NULL )
			RegCloseKey( hkKey );
		return READ_REG_FAIL;
	}

	if( iFullSize > maxsize + 1 )
		buffer[ maxsize + 1] = 0;
	
	if( hkInput == NULL )
		RegCloseKey( hkKey );
	
	return type;
}

//*---------------------------------------------------------------------------------
//| WriteRegBinary is similar to WriteRegDWORD except it dumps an arbitrary binary section
//| of data
//*---------------------------------------------------------------------------------
void WriteRegBinary( HKEY hkInput, char *item, unsigned char *data, int size )
{
	HKEY	hkKey;
	
	if( hkInput == NULL )
	{
		if( RegOpenKeyEx(
			HKEY_CURRENT_USER,		// handle of open key 
			REGNAME,				// address of name of subkey to open 
			0,						// reserved 
			KEY_WRITE,				// security access mask 
			&hkKey 					// address of handle of open key 
			)!=ERROR_SUCCESS )
		{
			LoadString( NULL, IDS_REG_OPEN_ERROR, gcErrorString, LOADSTRING_STRING_SIZE );
			MessageBox( MainhWnd, gcErrorString, "Atari800Win", MB_ICONSTOP );
			return;
		}
	}
	else
		hkKey = hkInput;
	
	if( RegSetValueEx(
		hkKey,					// handle of key to set value for  
		item,					// address of value to set 
		0,						// reserved 
		REG_BINARY,				// flag for value type 
		data,					// address of value data 
		size					// data buffer size
		)!=ERROR_SUCCESS )
	{
		LoadString( NULL, IDS_REG_WRITE_ERROR, gcErrorString, LOADSTRING_STRING_SIZE );
		MessageBox( MainhWnd, gcErrorString, "Atari800Win", MB_ICONSTOP );
	}	
	if( hkInput == NULL )
		RegCloseKey( hkKey );
}

//*---------------------------------------------------------------------------------
//| WriteRegString is similar to WriteRegBinary except it writes a null-terminated
//| string
//*---------------------------------------------------------------------------------
void WriteRegString( HKEY hkInput, char *item, char *data )
{
	HKEY	hkKey;
	
	if( hkInput == NULL )
	{
		if( RegOpenKeyEx(
			HKEY_CURRENT_USER,		// handle of open key 
			REGNAME,				// address of name of subkey to open 
			0,						// reserved 
			KEY_WRITE,				// security access mask 
			&hkKey 					// address of handle of open key 
			)!=ERROR_SUCCESS )
		{
			LoadString( NULL, IDS_REG_OPEN_ERROR, gcErrorString, LOADSTRING_STRING_SIZE );
			MessageBox( MainhWnd, gcErrorString, "Atari800Win", MB_ICONSTOP );
			return;
		}
	}
	else
		hkKey = hkInput;
	
	if( RegSetValueEx(
		hkKey,					// handle of key to set value for  
		item,					// address of value to set 
		0,						// reserved 
		REG_SZ,					// flag for value type 
		(const unsigned char *)data,					// address of value data 
		strlen( data )			// data buffer size
		)!=ERROR_SUCCESS )
	{
		LoadString( NULL, IDS_REG_WRITE_ERROR, gcErrorString, LOADSTRING_STRING_SIZE );
		MessageBox( MainhWnd, gcErrorString, "Atari800Win", MB_ICONSTOP );
	}	
	if( hkInput == NULL )
		RegCloseKey( hkKey );
}

void WriteAtari800Drives( HKEY hkInput )
{
	HKEY	hkKey = NULL;

	if( hkInput == NULL )
	{
		if( RegOpenKeyEx(
			HKEY_CURRENT_USER,		// handle of open key 
			REGNAME,				// address of name of subkey to open 
			0,						// reserved 
			KEY_ALL_ACCESS,				// security access mask 
			&hkKey 					// address of handle of open key 
			)!=ERROR_SUCCESS )
		{
			LoadString( NULL, IDS_REG_OPEN_ERROR, gcErrorString, LOADSTRING_STRING_SIZE );
			MessageBox( MainhWnd, gcErrorString, "Atari800Win", MB_ICONSTOP );
			return;
		}
	}
	else
		hkKey = hkInput;

	WriteRegString( hkKey, REG_HD1, atari_h1_dir );
	WriteRegString( hkKey, REG_HD2, atari_h2_dir );
	WriteRegString( hkKey, REG_HD3, atari_h3_dir );
	WriteRegString( hkKey, REG_HD4, atari_h4_dir );

	WriteRegString( hkKey, szDriveRegID[0], sio_filename[0] );
	WriteRegString( hkKey, szDriveRegID[1], sio_filename[1] );
	WriteRegString( hkKey, szDriveRegID[2], sio_filename[2] );
	WriteRegString( hkKey, szDriveRegID[3], sio_filename[3] );
	WriteRegString( hkKey, szDriveRegID[4], sio_filename[4] );
	WriteRegString( hkKey, szDriveRegID[5], sio_filename[5] );
	WriteRegString( hkKey, szDriveRegID[6], sio_filename[6] );
	WriteRegString( hkKey, szDriveRegID[7], sio_filename[7] );

	WriteRegString( hkKey, REG_EXEPATH, atari_exe_dir );

	if( hkInput == NULL )
		RegCloseKey( hkKey );
}

void WriteAtari800Registry( HKEY hkInput )
{
	HKEY	hkKey = NULL;

	if( hkInput == NULL )
	{
		if( RegOpenKeyEx(
			HKEY_CURRENT_USER,		// handle of open key 
			REGNAME,				// address of name of subkey to open 
			0,						// reserved 
			KEY_ALL_ACCESS,				// security access mask 
			&hkKey 					// address of handle of open key 
			)!=ERROR_SUCCESS )
		{
			LoadString( NULL, IDS_REG_OPEN_ERROR, gcErrorString, LOADSTRING_STRING_SIZE );
			MessageBox( MainhWnd, gcErrorString, "Atari800Win", MB_ICONSTOP );
			return;
		}
	}
	else
		hkKey = hkInput;

	WriteRegDWORD( hkKey, REG_REFRESH_RATE, refresh_rate );
	WriteRegDWORD( hkKey, REG_DEFAULT_SYSTEM, default_system );
	WriteRegDWORD( hkKey, REG_DEFAULT_TV_MODE, default_tv_mode );
	WriteRegDWORD( hkKey, REG_HOLD_OPTION, hold_option );
	WriteRegDWORD( hkKey, REG_ENABLE_SIO_PATCH, enable_sio_patch );
	WriteRegDWORD( hkKey, REG_ENABLE_C000_RAM, enable_c000_ram );
	WriteRegDWORD( hkKey, REG_ENABLE_ROM_PATCH, enable_rom_patches );
	WriteRegDWORD( hkKey, REG_MISC_STATES, ulMiscStates );
	WriteRegDWORD( hkKey, REG_CART_TYPE, cart_type );
	WriteRegDWORD( hkKey, REG_ARTIF_MODE, global_artif_mode );
	WriteRegString( hkKey, REG_OSA_ROM, atari_osa_filename );
	WriteRegString( hkKey, REG_OSB_ROM, atari_osb_filename );
	WriteRegString( hkKey, REG_XLXE_ROM, atari_xlxe_filename );
	WriteRegString( hkKey, REG_5200_ROM, atari_5200_filename );
	WriteRegString( hkKey, REG_BASIC_ROM, atari_basic_filename );
	WriteRegString( hkKey, REG_KEY_TEMPLATE, szTemplateFile );

	WriteRegDWORD( hkKey, REG_DDRAW_MODE, ulScreenMode );
	WriteRegDWORD( hkKey, REG_START_XPOS, nStartX );
	WriteRegDWORD( hkKey, REG_START_YPOS, nStartY );
	WriteRegDWORD( hkKey, REG_SOUND_STATE, ulSoundState );
	WriteRegDWORD( hkKey, REG_SOUND_RATE, nSoundRate );
	WriteRegDWORD( hkKey, REG_SOUND_VOLUME, nSoundVol );
	WriteRegDWORD( hkKey, REG_DONT_SHOW, ulDontShowFlags );
	WriteRegDWORD( hkKey, REG_JOYSTICKS, ulJoystickSelects );
	WriteRegDWORD( hkKey, REG_STICK_REPEAT, nJoyRepeat );
	WriteRegDWORD( hkKey, REG_STICK_SKIP, nJoySkip );
	WriteRegDWORD( hkKey, REG_CURRENT_REV, nVersion );

	WriteAtari800Drives( hkKey );

	if( hkInput == NULL )
		RegCloseKey( hkKey );
}

void WriteInitialReg( HKEY hkInput, BOOL bErasePaths )
{
	int i;
	HKEY	hkKey;

	if( !hkInput )
	{
		DWORD	disposition = REG_OPENED_EXISTING_KEY;
		
		if( RegOpenKeyEx(
			HKEY_CURRENT_USER,		// handle of open key 
			REGNAME,				// address of name of subkey to open 
			0,						// reserved 
			KEY_READ,				// security access mask 
			&hkKey 					// address of handle of open key 
			)!=ERROR_SUCCESS )
		{
			if( RegCreateKeyEx(
				HKEY_CURRENT_USER,		// handle of an open key 
				REGNAME,				// address of subkey name 
				0,						// reserved 
				"Atari800Win",			// address of class string 
				REG_OPTION_NON_VOLATILE,// special options flag 
				KEY_ALL_ACCESS,			// desired security access 
				NULL,					// address of key security structure 
				&hkKey,					// address of buffer for opened handle  
				&disposition 			// address of disposition value buffer 
				)!=ERROR_SUCCESS )
			{
				LoadString( NULL, IDS_REG_OPEN_ERROR, gcErrorString, LOADSTRING_STRING_SIZE );
				MessageBox( MainhWnd, gcErrorString, "Atari800Win", MB_ICONSTOP );
				//Probably should make this fault in a more elegant manner
				exit( 1 );
			}
		}
	}
	else
		hkKey = hkInput;

	refresh_rate = 1;
	default_system = 2;
	default_tv_mode = 2;
	hold_option = 1;
	enable_c000_ram = 0;
	enable_sio_patch = 1;
	enable_rom_patches = 1;
	cart_type = 0;
	global_artif_mode = 3;
	ulMiscStates = ATARI_STICK_RELEASE;

	if( bErasePaths )
	{
		char	szDirPath[ MAX_PATH ];

		GetCurrentDirectory( MAX_PATH, szDirPath );

		strcpy( atari_osa_filename, szDirPath );
		strcat( atari_osa_filename, "\\atariosa.rom" );

		strcpy( atari_osb_filename, szDirPath );
		strcat( atari_osb_filename, "\\atariosb.rom" );

		strcpy( atari_xlxe_filename, szDirPath );
		strcat( atari_xlxe_filename, "\\atarixl.rom" );

		strcpy( atari_5200_filename, szDirPath );
		strcat( atari_5200_filename, "\\atari5200.rom" );
		
		strcpy( atari_basic_filename, szDirPath );
		strcpy( atari_basic_filename, "\\ataribas.rom" );

		strcpy( szTemplateFile, ".\\keyboard.a8k" );
		WriteRegString( NULL, REG_OTHER_ROM, "None" );
		WriteRegString( NULL, REG_CURRENT_ROM, "None" );

		strcpy( atari_h1_dir, "." );
		strcpy( atari_h2_dir, "." );
		strcpy( atari_h3_dir, "." );
		strcpy( atari_h4_dir, "." );

		strcpy( atari_exe_dir, "." );
	}

	strcpy( sio_filename[0], "Empty" );
	for( i=1; i < 8; i++ )
	{
		strcpy( sio_filename[i], "Off" ) ;
	}

	WriteAtari800Registry( hkKey );

	if( hkInput == NULL )
		RegCloseKey( hkKey );
}

BOOL ReadRegPaths( HKEY hkInput )
{
	HKEY	hkKey = NULL;
	BOOL	bRegFail = FALSE;
	char	szDirPath[ MAX_PATH ];

	GetCurrentDirectory( MAX_PATH, szDirPath );
	if( !hkInput )
	{
		if( RegOpenKeyEx(
			HKEY_CURRENT_USER,		// handle of open key 
			REGNAME,				// address of name of subkey to open 
			0,						// reserved 
			KEY_READ,				// security access mask 
			&hkKey 					// address of handle of open key 
			)!=ERROR_SUCCESS )
		{
			LoadString( NULL, IDS_REG_OPEN_ERROR, gcErrorString, LOADSTRING_STRING_SIZE );
			MessageBox( MainhWnd, gcErrorString, "Atari800Win", MB_ICONSTOP );
			return TRUE;
		}
	}
	else
		hkKey = hkInput;

	if( (ReadRegBinary( hkInput, REG_OSA_ROM, atari_osa_filename, MAX_PATH, FALSE ))==READ_REG_FAIL )
	{
		strcpy( atari_osa_filename, szDirPath );
		strcat( atari_osa_filename, "\\atariosa.rom" );
		bRegFail = TRUE;
	}
	
	if( (ReadRegBinary( hkInput, REG_OSB_ROM, atari_osb_filename, MAX_PATH, FALSE ))==READ_REG_FAIL )
	{
		strcpy( atari_osb_filename, szDirPath );
		strcat( atari_osb_filename, "\\atariosb.rom" );
		bRegFail = TRUE;
	}
	
	if( (ReadRegBinary( hkInput, REG_XLXE_ROM, atari_xlxe_filename, MAX_PATH, FALSE ))==READ_REG_FAIL )
	{
		strcpy( atari_xlxe_filename, szDirPath );
		strcat( atari_xlxe_filename, "\\atarixl.rom" );
		bRegFail = TRUE;
	}
	
	if( (ReadRegBinary( hkInput, REG_5200_ROM, atari_5200_filename, MAX_PATH, FALSE ))==READ_REG_FAIL )
	{
		strcpy( atari_5200_filename, szDirPath );
		strcat( atari_5200_filename, "\\atari5200.rom" );
		bRegFail = TRUE;
	}
	
	if( (ReadRegBinary( hkInput, REG_BASIC_ROM, atari_basic_filename, MAX_PATH, FALSE ))==READ_REG_FAIL )
	{
		strcpy( atari_basic_filename, szDirPath );
		strcpy( atari_basic_filename, "\\ataribas.rom" );
		bRegFail = TRUE;
	}

	if( (ReadRegBinary( hkInput, REG_KEY_TEMPLATE, szTemplateFile, MAX_PATH, FALSE ))==READ_REG_FAIL )
	{
		strcpy( szTemplateFile, ".\\keyboard.a8k" );
		bRegFail = TRUE;
	}
	
	if( (ReadRegBinary( hkInput, REG_CURRENT_ROM, current_rom, MAX_PATH, FALSE ))==READ_REG_FAIL )
	{
		strcpy( current_rom, "None" );
		bRegFail = TRUE;
	}
	
	if( (ReadRegBinary( hkInput, REG_HD1, atari_h1_dir, MAX_PATH, FALSE ))==READ_REG_FAIL )
	{
		strcpy( atari_h1_dir, "Empty" );
		bRegFail = TRUE;
	}

	if( (ReadRegBinary( hkInput, REG_HD2, atari_h2_dir, MAX_PATH, FALSE ))==READ_REG_FAIL )
	{
		strcpy( atari_h2_dir, "Empty" );
		bRegFail = TRUE;
	}

	if( (ReadRegBinary( hkInput, REG_HD3, atari_h3_dir, MAX_PATH, FALSE ))==READ_REG_FAIL )
	{
		strcpy( atari_h3_dir, "Empty" );
		bRegFail = TRUE;
	}

	if( (ReadRegBinary( hkInput, REG_HD4, atari_h4_dir, MAX_PATH, FALSE ))==READ_REG_FAIL )
	{
		strcpy( atari_h4_dir, "Empty" );
		bRegFail = TRUE;
	}
	
	if( (ReadRegBinary( hkInput, REG_EXEPATH, atari_exe_dir, MAX_PATH, FALSE ))==READ_REG_FAIL )
	{
		strcpy( atari_exe_dir, "." );
		bRegFail = TRUE;
	}

	if( hkInput == NULL )
		RegCloseKey( hkKey );

	return bRegFail;
}

void ReadRegDrives( HKEY hkInput )
{
	HKEY	hkKey = NULL;
	BOOL	bRegFail = FALSE;
	int i;

	if( !hkInput )
	{
		if( RegOpenKeyEx(
			HKEY_CURRENT_USER,		// handle of open key 
			REGNAME,				// address of name of subkey to open 
			0,						// reserved 
			KEY_READ,				// security access mask 
			&hkKey 					// address of handle of open key 
			)!=ERROR_SUCCESS )
		{
			LoadString( NULL, IDS_REG_OPEN_ERROR, gcErrorString, LOADSTRING_STRING_SIZE );
			MessageBox( MainhWnd, gcErrorString, "Atari800Win", MB_ICONSTOP );
			return;
		}
	}
	else
		hkKey = hkInput;

	if( (ReadRegBinary( hkKey, szDriveRegID[0], sio_filename[0], MAX_PATH, FALSE ))==READ_REG_FAIL )
	{
		strcpy( sio_filename[0], "Empty" );
		bRegFail = TRUE;
	}
	if( (ReadRegBinary( hkKey, szDriveRegID[1], sio_filename[1], MAX_PATH, FALSE ))==READ_REG_FAIL )
	{
		strcpy( sio_filename[1], "Empty" );
		bRegFail = TRUE;
	}
	if( (ReadRegBinary( hkKey, szDriveRegID[2], sio_filename[2], MAX_PATH, FALSE ))==READ_REG_FAIL )
	{
		strcpy( sio_filename[2], "Empty" );
		bRegFail = TRUE;
	}
	if( (ReadRegBinary( hkKey, szDriveRegID[3], sio_filename[3], MAX_PATH, FALSE ))==READ_REG_FAIL )
	{
		strcpy( sio_filename[3], "Empty" );
		bRegFail = TRUE;
	}
	if( (ReadRegBinary( hkKey, szDriveRegID[4], sio_filename[4], MAX_PATH, FALSE ))==READ_REG_FAIL )
	{
		strcpy( sio_filename[4], "Empty" );
		bRegFail = TRUE;
	}
	if( (ReadRegBinary( hkKey, szDriveRegID[5], sio_filename[5], MAX_PATH, FALSE ))==READ_REG_FAIL )
	{
		strcpy( sio_filename[5], "Empty" );
		bRegFail = TRUE;
	}
	if( (ReadRegBinary( hkKey, szDriveRegID[6], sio_filename[6], MAX_PATH, FALSE ))==READ_REG_FAIL )
	{
		strcpy( sio_filename[6], "Empty" );
		bRegFail = TRUE;
	}
	if( (ReadRegBinary( hkKey, szDriveRegID[7], sio_filename[7], MAX_PATH, FALSE ))==READ_REG_FAIL )
	{
		strcpy( sio_filename[7], "Empty" );
		bRegFail = TRUE;
	}

	for( i = 0; i < 8; i++ )
	{
		if( *sio_filename[i] == 0 )
			strcpy( sio_filename[i], "Empty" );
	}

	if( hkInput == NULL )
		RegCloseKey( hkKey );

	if( bRegFail )
		WriteAtari800Registry( NULL );
}

//*---------------------------------------------------------------------------------
//| HandleRegistry() - Create the Registry entries if they don't exist and read all
//|	the defaults in at runtime (this is called from MainFrame)
//*---------------------------------------------------------------------------------
BOOL HandleRegistry( void )
{
	DWORD	disposition = REG_OPENED_EXISTING_KEY;
	HKEY	hkInitKey;
	BOOL	bRegFail = FALSE;
	BOOL	bInitialReg = FALSE;

	if( RegOpenKeyEx(
		HKEY_CURRENT_USER,		// handle of open key 
		REGNAME,				// address of name of subkey to open 
		0,						// reserved 
		KEY_ALL_ACCESS,			// security access mask 
		&hkInitKey 				// address of handle of open key 
		)!=ERROR_SUCCESS )
	{
		if( RegCreateKeyEx(
			HKEY_CURRENT_USER,		// handle of an open key 
			REGNAME,				// address of subkey name 
			0,						// reserved 
			"Atari800Win",			// address of class string 
			REG_OPTION_NON_VOLATILE,// special options flag 
			KEY_ALL_ACCESS,			// desired security access 
			NULL,					// address of key security structure 
			&hkInitKey,				// address of buffer for opened handle  
			&disposition 			// address of disposition value buffer 
			)!=ERROR_SUCCESS )
		{
			LoadString( NULL, IDS_REG_OPEN_ERROR, gcErrorString, LOADSTRING_STRING_SIZE );
			MessageBox( MainhWnd, gcErrorString, "Atari800Win", MB_ICONSTOP );
			//Probably should make this fault in a more elegant manner
			exit( 1 );
		}
	}
	
	// If the key doesn't exist, fill in defaults. This is the only time these
	// will be written all at once. From here on out we trust the Registry to hold them
	// (yeah, right) and update when key dialogs are used to configure them
	if( disposition == REG_CREATED_NEW_KEY )
	{
		bInitialReg = TRUE;

		if( !TestRomPaths( ) )
			WriteInitialReg( hkInitKey, TRUE );
		else
			WriteInitialReg( hkInitKey, FALSE );
	}
	else
	{
		//Read in the values from the Registry. Only fail and return error when it
		//is REALLY fatal (you never know what somebody might do with their registry)
		//For most of these an error will result in the value being the default run-time
		if( (ReadRegDWORD( hkInitKey, REG_CURRENT_REV, (DWORD *)&nVersion, FALSE))==READ_REG_FAIL )
			nVersion = CURRENT_REV - 1;
		
		if( nVersion != CURRENT_REV )
		{
			char	message[LOADSTRING_STRING_SIZE];
			LoadString( NULL, IDS_WARNING_OUTDATED_VERSION, message, LOADSTRING_STRING_SIZE );
			MessageBox( MainhWnd, message, "Atari800Win", MB_OK );
			nVersion = CURRENT_REV;

			ReadRegPaths( hkInitKey );	/* Since we already have a registry, read the paths + filenames at least */
										/* Note that this will have to change if I ever invalidate the path system (unlikely) */

			DeleteAllRegKeys( hkInitKey, REGNAME );
			RegCloseKey( hkInitKey );
			if( RegCreateKeyEx(
				HKEY_CURRENT_USER,		// handle of an open key 
				REGNAME,				// address of subkey name 
				0,						// reserved 
				"Atari800Win",			// address of class string 
				REG_OPTION_NON_VOLATILE,// special options flag 
				KEY_ALL_ACCESS,			// desired security access 
				NULL,					// address of key security structure 
				&hkInitKey,				// address of buffer for opened handle  
				&disposition 			// address of disposition value buffer 
				)!=ERROR_SUCCESS )
			{
				LoadString( NULL, IDS_REG_OPEN_ERROR, gcErrorString, LOADSTRING_STRING_SIZE );
				MessageBox( MainhWnd, gcErrorString, "Atari800Win", MB_ICONSTOP );
				//Probably should make this fault in a more elegant manner
				exit( 1 );
			}

			WriteInitialReg( hkInitKey, FALSE);
			bInitialReg = TRUE;
		}
		else
		{
			if( (ReadRegDWORD( hkInitKey, REG_REFRESH_RATE, (DWORD *)&refresh_rate, TRUE ))==READ_REG_FAIL )
			{
				refresh_rate = 1;
				bRegFail = TRUE;
			}
			
			if( (ReadRegDWORD( hkInitKey, REG_DEFAULT_SYSTEM, (DWORD *)&default_system, TRUE ))==READ_REG_FAIL )
			{
				default_system = 3;
				bRegFail = TRUE;
			}
			
			if( (ReadRegDWORD( hkInitKey, REG_DEFAULT_TV_MODE, (DWORD *)&default_tv_mode, TRUE ))==READ_REG_FAIL )
			{
				default_tv_mode = 2;
				bRegFail = TRUE;
			}
			
			if( (ReadRegDWORD( hkInitKey, REG_HOLD_OPTION, (DWORD *)&hold_option, TRUE ))==READ_REG_FAIL )
			{
				hold_option = 0;
				bRegFail = TRUE;
			}
			
			if( (ReadRegDWORD( hkInitKey, REG_ENABLE_C000_RAM, (DWORD *)&enable_c000_ram, TRUE ))==READ_REG_FAIL )
			{
				enable_c000_ram = 0;
				bRegFail = TRUE;
			}
			
			if( (ReadRegDWORD( hkInitKey, REG_ENABLE_SIO_PATCH, (DWORD *)&enable_sio_patch, TRUE ))==READ_REG_FAIL )
			{
				enable_sio_patch = 1;
				bRegFail = TRUE;
			}

			if( (ReadRegDWORD( hkInitKey, REG_ENABLE_ROM_PATCH, (DWORD *)&enable_rom_patches, TRUE ))==READ_REG_FAIL )
			{
				enable_rom_patches = 1;
				bRegFail = TRUE;
			}

			if( (ReadRegDWORD( hkInitKey, REG_ARTIF_MODE, (DWORD *)&global_artif_mode, TRUE ))== READ_REG_FAIL )
			{
				global_artif_mode = 3;
				bRegFail = TRUE;
			}

			if( (ReadRegDWORD( hkInitKey, REG_DDRAW_MODE, (DWORD *)&ulScreenMode, FALSE ))==READ_REG_FAIL )
			{
				ulScreenMode = DISPLAY_MODE_DEFAULT;
				bRegFail = TRUE;
			}

			if( (ReadRegDWORD( hkInitKey, REG_START_XPOS, (DWORD *)&nStartX, FALSE ))==READ_REG_FAIL )
			{
				nStartX = 0;
				bRegFail = TRUE;
			}

			if( nStartX < 0 )
				nStartX = 0;
			if( nStartX > GetSystemMetrics( SM_CXFULLSCREEN ) )
				nStartX = GetSystemMetrics( SM_CXFULLSCREEN ) - (ATARI_WIDTH);
			
			if( (ReadRegDWORD( hkInitKey, REG_START_YPOS, (DWORD *)&nStartY, FALSE ))==READ_REG_FAIL )
			{
				nStartY = 0;
				bRegFail = TRUE;
			}

			if( nStartY < 0 )
				nStartY = 0;
			if( nStartY > GetSystemMetrics( SM_CYFULLSCREEN ) )
				nStartY = GetSystemMetrics( SM_CYFULLSCREEN ) - ATARI_HEIGHT;
			
			if( (ReadRegDWORD( hkInitKey, REG_SOUND_STATE, (DWORD *)&ulSoundState, FALSE))==READ_REG_FAIL )
			{
				ulSoundState = SOUND_MMSOUND;
				bRegFail = TRUE;
			}

#ifndef USE_DSOUND
			if( !(ulSoundState & SOUND_NOSOUND) )
				ulSoundState |= SOUND_MMSOUND;
#endif

			if( (ReadRegDWORD( hkInitKey, REG_SOUND_RATE, (DWORD *)&nSoundRate, FALSE))==READ_REG_FAIL )
			{
				nSoundRate = 44100;
				bRegFail = TRUE;
			}

			if( (ReadRegDWORD( hkInitKey, REG_MISC_STATES, (DWORD *)&ulMiscStates, FALSE))==READ_REG_FAIL )
			{
				ulMiscStates = ATARI_STICK_RELEASE;
				bRegFail = TRUE;
			}

			if( (ReadRegDWORD( hkInitKey, REG_SOUND_VOLUME, (DWORD *)&nSoundVol, FALSE))==READ_REG_FAIL )
			{
				nSoundVol = 0;
				bRegFail = TRUE;
			}

			if( (ReadRegDWORD( hkInitKey, REG_DONT_SHOW, (DWORD *)&ulDontShowFlags, FALSE))==READ_REG_FAIL )
			{
				ulDontShowFlags = 0;
				bRegFail = TRUE;
			}

			if( (ReadRegDWORD( hkInitKey, REG_STICK_REPEAT, (DWORD *)&nJoyRepeat, FALSE))==READ_REG_FAIL )
			{
				nJoyRepeat = 0;
				bRegFail = TRUE;
			}

			if( (ReadRegDWORD( hkInitKey, REG_STICK_SKIP, (DWORD *)&nJoySkip, FALSE))==READ_REG_FAIL )
			{
				nJoySkip = 0;
				bRegFail = TRUE;
			}

			if( (ReadRegDWORD( hkInitKey, REG_JOYSTICKS, (DWORD *)&ulJoystickSelects, FALSE)) == READ_REG_FAIL )
			{
				ulJoystickSelects = 0x7F7F7FFF;
				bRegFail = TRUE;
			}

			if( (ReadRegDWORD( hkInitKey, REG_CART_TYPE, (DWORD *)&cart_type, FALSE))==READ_REG_FAIL )
			{
				cart_type = 0;
				bRegFail = TRUE;
			}

			if( ReadRegPaths( NULL ) )
				bRegFail = TRUE;
		}
	}
	RegCloseKey( hkInitKey );

	if( ulMiscStates & ATARI_USE_KEYTEMPLATE )
	{
		if( !ReadKeyTemplate( szTemplateFile ) )
		{
			char	szmessage[ MAX_PATH + 64 ];
			sprintf( szmessage, "Could not load keyboard template file %s, turning off keyboard template", szTemplateFile );
			MessageBox( NULL, szmessage, "Atari800Win", MB_OK );
			ulMiscStates &= ~ATARI_USE_KEYTEMPLATE;
		}
	}

	if( bRegFail )
		WriteAtari800Registry( NULL );

	return bInitialReg;
}

