#include "burner.h"
#include <ctype.h>

const double PI = 3.14159265358979323846f;			// Pi
const double DEGTORAD = 0.01745329251994329547f;	// Degrees to Radians
const double RADTODEG = 57.29577951308232286465f;	// Radians to Degrees

static int nExitStatus;

// -----------------------------------------------------------------------------

static INT_PTR CALLBACK DefInpProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM)
{
 	int nRet = 0;
	BOOL fTrue = FALSE;

	switch (Msg) {
		case WM_INITDIALOG:
			nRet = nAudSegCount;
			SetWindowText(hDlg, FBALoadStringEx(hAppInst, IDS_NUMDIAL_NUM_FRAMES, true));
			SetDlgItemInt(hDlg, IDC_VALUE_EDIT, nRet, TRUE);
			return TRUE;

		case WM_COMMAND:
			if (LOWORD(wParam) == ID_VALUE_CLOSE) {
				SendMessage(hDlg, WM_CLOSE, 0, 0);
			} else {
				if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDCANCEL) {
					SendMessage(hDlg, WM_CLOSE, 0, 0);
				}
			}
			break;

		case WM_CLOSE:
			nRet = GetDlgItemInt(hDlg, IDC_VALUE_EDIT, &fTrue, TRUE);
			if (fTrue) {
				nAudSegCount = nRet;
			}
			EndDialog(hDlg, 0);
	}

	return 0;
}

int NumDialCreate(int)
{
	FBADialogBox(hAppInst, MAKEINTRESOURCE(IDD_VALUE), hScrnWnd, (DLGPROC)DefInpProc);

	return 1;
}

// -----------------------------------------------------------------------------
// Gamma dialog

static INT_PTR CALLBACK GammaProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM)	// LPARAM lParam
{
	static double nPrevGamma;

	switch (Msg) {
		case WM_INITDIALOG: {
			TCHAR szText[16];
			int nPos;

			nPrevGamma = nGamma;
			nExitStatus = 0;

			WndInMid(hDlg, hScrnWnd);

			// Initialise gamma slider
			SendDlgItemMessage(hDlg, IDC_GAMMA_SLIDER, TBM_SETRANGE, (WPARAM)0, (LPARAM)MAKELONG(1, 20000));
			SendDlgItemMessage(hDlg, IDC_GAMMA_SLIDER, TBM_SETLINESIZE, (WPARAM)0, (LPARAM)200);
			SendDlgItemMessage(hDlg, IDC_GAMMA_SLIDER, TBM_SETPAGESIZE, (WPARAM)0, (LPARAM)250);
			SendDlgItemMessage(hDlg, IDC_GAMMA_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)7500);
			SendDlgItemMessage(hDlg, IDC_GAMMA_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)10001);
			SendDlgItemMessage(hDlg, IDC_GAMMA_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)12500);

			// Set slider to value of nGamma
			if (nGamma > 1.0) {		// Gamma > 1
				nPos = int((nGamma - 1.0) * 10000.0 + 10001.0);
			} else {				// Gamma < 1
				nPos = int(10000.0f - ((1.0 / nGamma) * 10000.0 - 10000.0));
			}
			SendDlgItemMessage(hDlg, IDC_GAMMA_SLIDER, TBM_SETPOS, (WPARAM)true, (LPARAM)nPos);

			// Set the edit control to the value of nGamma
			_stprintf(szText, _T("%0.2f"), nGamma);
			SendDlgItemMessage(hDlg, IDC_GAMMA_EDIT, WM_SETTEXT, (WPARAM)0, (LPARAM)szText);

			// Update the screen
			ComputeGammaLUT();
			if (bVidOkay) {
				VidRedraw();
				VidPaint(0);
			}

			return TRUE;
		}
		case WM_COMMAND: {
			switch (HIWORD(wParam)) {
				case BN_CLICKED: {
					if (LOWORD(wParam) == IDOK) {
						nExitStatus = 1;
						SendMessage(hDlg, WM_CLOSE, 0, 0);
					}
					if (LOWORD(wParam) == IDCANCEL) {
						nExitStatus = -1;
						SendMessage(hDlg, WM_CLOSE, 0, 0);
					}
					break;
				}
				case EN_UPDATE: {
					if (nExitStatus == 0) {
						TCHAR szText[16] = _T("");
						bool bPoint = 0;
						bool bValid = 1;

						if (SendDlgItemMessage(hDlg, IDC_GAMMA_EDIT, WM_GETTEXTLENGTH, (WPARAM)0, (LPARAM)0) < 16) {
							SendDlgItemMessage(hDlg, IDC_GAMMA_EDIT, WM_GETTEXT, (WPARAM)16, (LPARAM)szText);
						}

						// Scan string in the edit control for illegal characters
						for (int i = 0; szText[i]; i++) {
							if (szText[i] == _T('.')) {
								if (bPoint) {
									bValid = 0;
									break;
								}
							} else {
								if (!_istdigit(szText[i])) {
									bValid = 0;
									break;
								}
							}
						}

						if (bValid) {
							int nPos;

							nGamma = _tcstod(szText, NULL);

							// Set slider to value of nGamma
							if (nGamma > 1.0) {		// Gamma > 1
								nPos = int((nGamma - 1.0) * 10000.0 + 10001.0);
							} else {				// Gamma < 1
								nPos = int(10000.0 - ((1.0 / nGamma) * 10000.0 - 10000.0));
							}
							SendDlgItemMessage(hDlg, IDC_GAMMA_SLIDER, TBM_SETPOS, (WPARAM)true, (LPARAM)nPos);

							// Update the screen
							ComputeGammaLUT();
							if (bVidOkay) {
								VidRedraw();
								VidPaint(0);
							}
						}
					}
					break;
				}
				break;
			}
		}

		case WM_HSCROLL: {
			switch (LOWORD(wParam)) {
				case TB_BOTTOM:
				case TB_ENDTRACK:
				case TB_LINEDOWN:
				case TB_LINEUP:
				case TB_PAGEDOWN:
				case TB_PAGEUP:
				case TB_THUMBPOSITION:
				case TB_THUMBTRACK:
				case TB_TOP: {
					if (nExitStatus == 0) {
						TCHAR szText[16];
						int nPos;

						// Update the contents of the edit control
						nPos = SendDlgItemMessage(hDlg, IDC_GAMMA_SLIDER, TBM_GETPOS, (WPARAM)0, (LPARAM)0);
						if (nPos > 10000) {	// Gamma > 1
							nGamma = 1.0 + (nPos - 10000.0) / 10000.0;
						} else {			// Gamma < 1
							nGamma = 1.0 / (1.0 + ((10001.0 - nPos) / 10000.0));
						}
						_stprintf(szText, _T("%0.2f"), nGamma);
						SendDlgItemMessage(hDlg, IDC_GAMMA_EDIT, WM_SETTEXT, (WPARAM)0, (LPARAM)szText);

						// Update the screen
						ComputeGammaLUT();
						if (bVidOkay) {
							VidRedraw();
							VidPaint(0);
						}
					}
					break;
				}
			}
			break;
		}

		case WM_CLOSE:
			if (nExitStatus != 1) {
				nGamma = nPrevGamma;
			}
			EndDialog(hDlg, 0);
	}

	return 0;
}

void GammaDialog()
{
	FBADialogBox(hAppInst, MAKEINTRESOURCE(IDD_GAMMA), hScrnWnd, (DLGPROC)GammaProc);
}

// -----------------------------------------------------------------------------
// Scanline intensity dialog

static INT_PTR CALLBACK ScanlineProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM)	// LPARAM lParam
{
	static int nPrevIntensity;

	switch (Msg) {
		case WM_INITDIALOG: {
			TCHAR szText[16];
			nPrevIntensity = nVidScanIntensity;
			nExitStatus = 0;

			WndInMid(hDlg, hScrnWnd);

			// Initialise slider
			SendDlgItemMessage(hDlg, IDC_SCANLINE_SLIDER, TBM_SETRANGE, (WPARAM)0, (LPARAM)MAKELONG(0, 255));
			SendDlgItemMessage(hDlg, IDC_SCANLINE_SLIDER, TBM_SETPAGESIZE, (WPARAM)0, (LPARAM)16);
			SendDlgItemMessage(hDlg, IDC_SCANLINE_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)191);
			SendDlgItemMessage(hDlg, IDC_SCANLINE_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)127);
			SendDlgItemMessage(hDlg, IDC_SCANLINE_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)63);

			// Set slider to current value
			SendDlgItemMessage(hDlg, IDC_SCANLINE_SLIDER, TBM_SETPOS, (WPARAM)true, (LPARAM)nVidScanIntensity & 0xFF);

			// Set the edit control to current value
			_stprintf(szText, _T("%i"), nVidScanIntensity & 0xFF);
			SendDlgItemMessage(hDlg, IDC_SCANLINE_EDIT, WM_SETTEXT, (WPARAM)0, (LPARAM)szText);

			// Update the screen
			if (bDrvOkay) {
				VidPaint(2);
			}

			return TRUE;
		}
		case WM_COMMAND: {
			switch (HIWORD(wParam)) {
				case BN_CLICKED: {
					if (LOWORD(wParam) == IDOK) {
						nExitStatus = 1;
						SendMessage(hDlg, WM_CLOSE, 0, 0);
					}
					if (LOWORD(wParam) == IDCANCEL) {
						nExitStatus = -1;
						SendMessage(hDlg, WM_CLOSE, 0, 0);
					}
					break;
				}
				case EN_UPDATE: {
					if (nExitStatus == 0) {
						TCHAR szText[16] = _T("");
						bool bValid = 1;

						if (SendDlgItemMessage(hDlg, IDC_SCANLINE_EDIT, WM_GETTEXTLENGTH, (WPARAM)0, (LPARAM)0) < 16) {
							SendDlgItemMessage(hDlg, IDC_SCANLINE_EDIT, WM_GETTEXT, (WPARAM)16, (LPARAM)szText);
						}

						// Scan string in the edit control for illegal characters
						for (int i = 0; szText[i]; i++) {
							if (!_istdigit(szText[i])) {
								bValid = 0;
								break;
							}
						}

						if (bValid) {
							nVidScanIntensity = _tcstol(szText, NULL, 0);
							if (nVidScanIntensity < 0) {
								nVidScanIntensity = 0;
							} else {
								if (nVidScanIntensity > 255) {
									nVidScanIntensity = 255;
								}
							}

							// Set slider to current value
							SendDlgItemMessage(hDlg, IDC_SCANLINE_SLIDER, TBM_SETPOS, (WPARAM)true, (LPARAM)nVidScanIntensity);

							nVidScanIntensity |= (nVidScanIntensity << 8) | (nVidScanIntensity << 16);

							// Update the screen
							if (bVidOkay) {
								VidPaint(2);
							}
						}
					}
					break;
				}
			}
			break;
		}

		case WM_HSCROLL: {
			switch (LOWORD(wParam)) {
				case TB_BOTTOM:
				case TB_ENDTRACK:
				case TB_LINEDOWN:
				case TB_LINEUP:
				case TB_PAGEDOWN:
				case TB_PAGEUP:
				case TB_THUMBPOSITION:
				case TB_THUMBTRACK:
				case TB_TOP: {
					if (nExitStatus == 0) {
						TCHAR szText[16];

						// Update the contents of the edit control
						nVidScanIntensity = SendDlgItemMessage(hDlg, IDC_SCANLINE_SLIDER, TBM_GETPOS, (WPARAM)0, (LPARAM)0);
						_stprintf(szText, _T("%i"), nVidScanIntensity);
						SendDlgItemMessage(hDlg, IDC_SCANLINE_EDIT, WM_SETTEXT, (WPARAM)0, (LPARAM)szText);

						nVidScanIntensity |= (nVidScanIntensity << 8) | (nVidScanIntensity << 16);
						// Update the screen
						if (bVidOkay) {
//							VidRedraw();
							VidPaint(2);
						}
					}
					break;
				}
			}
			break;
		}

		case WM_CLOSE:
			if (nExitStatus != 1) {
				nVidScanIntensity = nPrevIntensity;
			}
			EndDialog(hDlg, 0);
			break;
	}

	return 0;
}

void ScanlineDialog()
{
	FBADialogBox(hAppInst, MAKEINTRESOURCE(IDD_SCANLINE), hScrnWnd, (DLGPROC)ScanlineProc);
}

// -----------------------------------------------------------------------------
// Feedback intensity dialog
static INT_PTR CALLBACK PhosphorProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam)	// LPARAM lParam
{
	static int nPrevIntensity;
	static int nPrevSaturation;

	switch (Msg) {
		case WM_INITDIALOG: {
			TCHAR szText[16];
			nPrevIntensity = nVidFeedbackIntensity;
			nPrevSaturation = nVidFeedbackOverSaturation;
			nExitStatus = 0;

			WndInMid(hDlg, hScrnWnd);

			// Initialise sliders
			SendDlgItemMessage(hDlg, IDC_PHOSPHOR_1_SLIDER, TBM_SETRANGE, (WPARAM)0, (LPARAM)MAKELONG(0, 255));
			SendDlgItemMessage(hDlg, IDC_PHOSPHOR_1_SLIDER, TBM_SETPAGESIZE, (WPARAM)0, (LPARAM)8);
			SendDlgItemMessage(hDlg, IDC_PHOSPHOR_1_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)127);
			SendDlgItemMessage(hDlg, IDC_PHOSPHOR_1_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)63);
			SendDlgItemMessage(hDlg, IDC_PHOSPHOR_1_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)31);
			SendDlgItemMessage(hDlg, IDC_PHOSPHOR_1_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)15);

			SendDlgItemMessage(hDlg, IDC_PHOSPHOR_2_SLIDER, TBM_SETRANGE, (WPARAM)0, (LPARAM)MAKELONG(0, 127));
			SendDlgItemMessage(hDlg, IDC_PHOSPHOR_2_SLIDER, TBM_SETPAGESIZE, (WPARAM)0, (LPARAM)4);
			SendDlgItemMessage(hDlg, IDC_PHOSPHOR_2_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)63);
			SendDlgItemMessage(hDlg, IDC_PHOSPHOR_2_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)31);
			SendDlgItemMessage(hDlg, IDC_PHOSPHOR_2_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)15);

			// Set slider to current values
			SendDlgItemMessage(hDlg, IDC_PHOSPHOR_1_SLIDER, TBM_SETPOS, (WPARAM)true, (LPARAM)nVidFeedbackIntensity);
			SendDlgItemMessage(hDlg, IDC_PHOSPHOR_2_SLIDER, TBM_SETPOS, (WPARAM)true, (LPARAM)nVidFeedbackOverSaturation);

			// Set the edit control to current values
			_stprintf(szText, _T("%i"), nVidFeedbackIntensity);
			SendDlgItemMessage(hDlg, IDC_PHOSPHOR_1_EDIT, WM_SETTEXT, (WPARAM)0, (LPARAM)szText);
			_stprintf(szText, _T("%i"), nVidFeedbackOverSaturation);
			SendDlgItemMessage(hDlg, IDC_PHOSPHOR_2_EDIT, WM_SETTEXT, (WPARAM)0, (LPARAM)szText);

			return TRUE;
		}
		case WM_COMMAND: {
			switch (HIWORD(wParam)) {
				case BN_CLICKED: {
					if (LOWORD(wParam) == IDOK) {
						nExitStatus = 1;
						SendMessage(hDlg, WM_CLOSE, 0, 0);
					}
					if (LOWORD(wParam) == IDCANCEL) {
						nExitStatus = -1;
						SendMessage(hDlg, WM_CLOSE, 0, 0);
					}
					break;
				}
				case EN_UPDATE: {
					if (nExitStatus == 0) {
						TCHAR szText[16] = _T("");
						bool bValid = 1;

						switch (LOWORD(wParam)) {
							case IDC_PHOSPHOR_1_EDIT:
								if (SendDlgItemMessage(hDlg, IDC_PHOSPHOR_1_EDIT, WM_GETTEXTLENGTH, (WPARAM)0, (LPARAM)0) < 16) {
									SendDlgItemMessage(hDlg, IDC_PHOSPHOR_1_EDIT, WM_GETTEXT, (WPARAM)16, (LPARAM)szText);
								}

								// Scan string in the edit control for illegal characters
								for (int i = 0; szText[i]; i++) {
									if (!_istdigit(szText[i])) {
										bValid = 0;
										break;
									}
								}

								if (bValid) {
									nVidFeedbackIntensity = _tcstol(szText, NULL, 0);
									if (nVidFeedbackIntensity < 0) {
										nVidFeedbackIntensity = 0;
									} else {
										if (nVidFeedbackIntensity > 255) {
											nVidFeedbackIntensity = 255;
										}
									}

									// Set slider to current value
									SendDlgItemMessage(hDlg, IDC_PHOSPHOR_1_SLIDER, TBM_SETPOS, (WPARAM)true, (LPARAM)nVidFeedbackIntensity);
								}
								break;
							case IDC_PHOSPHOR_2_EDIT:
								if (SendDlgItemMessage(hDlg, IDC_PHOSPHOR_2_EDIT, WM_GETTEXTLENGTH, (WPARAM)0, (LPARAM)0) < 16) {
									SendDlgItemMessage(hDlg, IDC_PHOSPHOR_2_EDIT, WM_GETTEXT, (WPARAM)16, (LPARAM)szText);
								}

								// Scan string in the edit control for illegal characters
								for (int i = 0; szText[i]; i++) {
									if (!_istdigit(szText[i])) {
										bValid = 0;
										break;
									}
								}

								if (bValid) {
									nVidFeedbackOverSaturation = _tcstol(szText, NULL, 0);
									if (nVidFeedbackOverSaturation < 0) {
										nVidFeedbackOverSaturation = 0;
									} else {
										if (nVidFeedbackOverSaturation > 255) {
											nVidFeedbackOverSaturation = 255;
										}
									}

									// Set slider to current value
									SendDlgItemMessage(hDlg, IDC_PHOSPHOR_2_SLIDER, TBM_SETPOS, (WPARAM)true, (LPARAM)nVidFeedbackOverSaturation);

									// Update the screen
									if (bVidOkay) {
										VidPaint(2);
									}
								}
								break;
						}
					}
					break;
				}
			}
			break;
		}

		case WM_HSCROLL: {
			switch (LOWORD(wParam)) {
				case TB_BOTTOM:
				case TB_ENDTRACK:
				case TB_LINEDOWN:
				case TB_LINEUP:
				case TB_PAGEDOWN:
				case TB_PAGEUP:
				case TB_THUMBPOSITION:
				case TB_THUMBTRACK:
				case TB_TOP: {
					if (nExitStatus == 0) {
						TCHAR szText[16];

						// Update the contents of the edit control
						switch (GetDlgCtrlID((HWND)lParam)) {
							case IDC_PHOSPHOR_1_SLIDER:
								nVidFeedbackIntensity = SendDlgItemMessage(hDlg, IDC_PHOSPHOR_1_SLIDER, TBM_GETPOS, (WPARAM)0, (LPARAM)0);
								_stprintf(szText, _T("%i"), nVidFeedbackIntensity);
								SendDlgItemMessage(hDlg, IDC_PHOSPHOR_1_EDIT, WM_SETTEXT, (WPARAM)0, (LPARAM)szText);
								break;
							case IDC_PHOSPHOR_2_SLIDER:
								nVidFeedbackOverSaturation = SendDlgItemMessage(hDlg, IDC_PHOSPHOR_2_SLIDER, TBM_GETPOS, (WPARAM)0, (LPARAM)0);
								_stprintf(szText, _T("%i"), nVidFeedbackOverSaturation);
								SendDlgItemMessage(hDlg, IDC_PHOSPHOR_2_EDIT, WM_SETTEXT, (WPARAM)0, (LPARAM)szText);
								break;
						}
					}
					break;
				}
			}
			break;
		}

		case WM_CLOSE:
			if (nExitStatus != 1) {
				nVidFeedbackIntensity = nPrevIntensity;
				nVidFeedbackOverSaturation = nPrevSaturation;
			}
			EndDialog(hDlg, 0);
			break;
	}

	return 0;
}

void PhosphorDialog()
{
	FBADialogBox(hAppInst, MAKEINTRESOURCE(IDD_PHOSPHOR), hScrnWnd, (DLGPROC)PhosphorProc);
}

// -----------------------------------------------------------------------------
// Screen Angle dialog
static INT_PTR CALLBACK ScreenAngleProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
{
	static float fPrevScreenAngle, fPrevScreenCurvature;
	static HWND hScreenAngleSlider, hScreenAngleEdit;

	switch (Msg) {
		case WM_INITDIALOG: {
			TCHAR szText[16];
			fPrevScreenAngle = fVidScreenAngle;
			fPrevScreenCurvature = fVidScreenCurvature;
			hScreenAngleSlider = GetDlgItem(hDlg, IDC_SCREENANGLE_SLIDER);
			hScreenAngleEdit = GetDlgItem(hDlg, IDC_SCREENANGLE_EDIT);
			nExitStatus = 0;

			WndInMid(hDlg, hScrnWnd);

			// Initialise sliders
			SendDlgItemMessage(hDlg, IDC_SCREENANGLE_SLIDER, TBM_SETRANGE, (WPARAM)0, (LPARAM)MAKELONG(0, 12000));
			SendDlgItemMessage(hDlg, IDC_SCREENANGLE_SLIDER, TBM_SETLINESIZE, (WPARAM)0, (LPARAM)100);
			SendDlgItemMessage(hDlg, IDC_SCREENANGLE_SLIDER, TBM_SETPAGESIZE, (WPARAM)0, (LPARAM)250);
			SendDlgItemMessage(hDlg, IDC_SCREENANGLE_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)1000);
			SendDlgItemMessage(hDlg, IDC_SCREENANGLE_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)2250);
			SendDlgItemMessage(hDlg, IDC_SCREENANGLE_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)6000);

			SendDlgItemMessage(hDlg, IDC_SCREENCURVATURE_SLIDER, TBM_SETRANGE, (WPARAM)0, (LPARAM)MAKELONG(0, 12000));
			SendDlgItemMessage(hDlg, IDC_SCREENCURVATURE_SLIDER, TBM_SETLINESIZE, (WPARAM)0, (LPARAM)150);
			SendDlgItemMessage(hDlg, IDC_SCREENCURVATURE_SLIDER, TBM_SETPAGESIZE, (WPARAM)0, (LPARAM)375);
			SendDlgItemMessage(hDlg, IDC_SCREENCURVATURE_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)3000);
			SendDlgItemMessage(hDlg, IDC_SCREENCURVATURE_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)4500);
			SendDlgItemMessage(hDlg, IDC_SCREENCURVATURE_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)6000);

			// Set sliders to current value
			SendDlgItemMessage(hDlg, IDC_SCREENANGLE_SLIDER, TBM_SETPOS, (WPARAM)true, (LPARAM)(fVidScreenAngle * RADTODEG * 100.0f));
			SendDlgItemMessage(hDlg, IDC_SCREENCURVATURE_SLIDER, TBM_SETPOS, (WPARAM)true, (LPARAM)(fVidScreenCurvature * RADTODEG * 150.0f));

			// Set the edit controls to current value
			_stprintf(szText, _T("%0.2f"), fVidScreenAngle * RADTODEG);
			SendDlgItemMessage(hDlg, IDC_SCREENANGLE_EDIT, WM_SETTEXT, (WPARAM)0, (LPARAM)szText);

			_stprintf(szText, _T("%0.2f"), fVidScreenCurvature * RADTODEG);
			SendDlgItemMessage(hDlg, IDC_SCREENCURVATURE_EDIT, WM_SETTEXT, (WPARAM)0, (LPARAM)szText);

			// Update the screen
			if (bVidOkay) {
				VidPaint(2);
			}

			return TRUE;
		}
		case WM_COMMAND: {
			switch (HIWORD(wParam)) {
				case BN_CLICKED: {
					if (LOWORD(wParam) == IDOK) {
						nExitStatus = 1;
						SendMessage(hDlg, WM_CLOSE, 0, 0);
					}
					if (LOWORD(wParam) == IDCANCEL) {
						nExitStatus = -1;
						SendMessage(hDlg, WM_CLOSE, 0, 0);
					}
					break;
				}
				case EN_UPDATE: {
					if (nExitStatus == 0) {
						TCHAR szText[16] = _T("");
						bool bPoint = 0;
						bool bValid = 1;

						if ((HWND)lParam == hScreenAngleEdit) {
							if (SendDlgItemMessage(hDlg, IDC_SCREENANGLE_EDIT, WM_GETTEXTLENGTH, (WPARAM)0, (LPARAM)0) < 16) {
								SendDlgItemMessage(hDlg, IDC_SCREENANGLE_EDIT, WM_GETTEXT, (WPARAM)16, (LPARAM)szText);
							}
						} else {
							if (SendDlgItemMessage(hDlg, IDC_SCREENCURVATURE_EDIT, WM_GETTEXTLENGTH, (WPARAM)0, (LPARAM)0) < 16) {
								SendDlgItemMessage(hDlg, IDC_SCREENCURVATURE_EDIT, WM_GETTEXT, (WPARAM)16, (LPARAM)szText);
							}
						}

						// Scan string in the edit control for illegal characters
						for (int i = 0; szText[i]; i++) {
							if (szText[i] == '.') {
								if (bPoint) {
									bValid = 0;
									break;
								}
							} else {
								if (!_istdigit(szText[i])) {
									bValid = 0;
									break;
								}
							}
						}

						if (bValid) {
							if ((HWND)lParam == hScreenAngleEdit) {
								fVidScreenAngle = _tcstod(szText, NULL) * DEGTORAD;
								if (fVidScreenAngle < 0.0f) {
									fVidScreenAngle = 0.0f;
								} else {
									if (fVidScreenAngle > PI / 1.5f) {
										fVidScreenAngle = PI / 1.5f;
									}
								}

								// Set slider to current value
								SendDlgItemMessage(hDlg, IDC_SCREENANGLE_SLIDER, TBM_SETPOS, (WPARAM)true, (LPARAM)(fVidScreenAngle * RADTODEG * 100.0f));
							} else {
								fVidScreenCurvature = _tcstod(szText, NULL) * DEGTORAD;
								if (fVidScreenCurvature < 0.0f) {
									fVidScreenCurvature = 0.0f;
								} else {
									if (fVidScreenCurvature > PI / 2.25f) {
										fVidScreenCurvature = PI / 2.25f;
									}
								}

								// Set slider to current value
								SendDlgItemMessage(hDlg, IDC_SCREENCURVATURE_SLIDER, TBM_SETPOS, (WPARAM)true, (LPARAM)(fVidScreenCurvature * RADTODEG * 150.0f));
							}

							// Update the screen
							if (bVidOkay) {
								VidPaint(2);
							}
						}
					}
					break;
				}
			}
			break;
		}

		case WM_HSCROLL: {
			switch (LOWORD(wParam)) {
				case TB_BOTTOM:
				case TB_ENDTRACK:
				case TB_LINEDOWN:
				case TB_LINEUP:
				case TB_PAGEDOWN:
				case TB_PAGEUP:
				case TB_THUMBPOSITION:
				case TB_THUMBTRACK:
				case TB_TOP: {
					if (nExitStatus == 0) {
						TCHAR szText[16];

						// Update the contents of the edit control
						if ((HWND)lParam == hScreenAngleSlider) {
							fVidScreenAngle = (float)SendDlgItemMessage(hDlg, IDC_SCREENANGLE_SLIDER, TBM_GETPOS, (WPARAM)0, (LPARAM)0) * DEGTORAD / 100.0f;
							_stprintf(szText, _T("%0.2f"), fVidScreenAngle * RADTODEG);
							SendDlgItemMessage(hDlg, IDC_SCREENANGLE_EDIT, WM_SETTEXT, (WPARAM)0, (LPARAM)szText);
						} else {
							fVidScreenCurvature = (float)SendDlgItemMessage(hDlg, IDC_SCREENCURVATURE_SLIDER, TBM_GETPOS, (WPARAM)0, (LPARAM)0) * DEGTORAD / 150.0f;
							_stprintf(szText, _T("%0.2f"), fVidScreenCurvature * RADTODEG);
							SendDlgItemMessage(hDlg, IDC_SCREENCURVATURE_EDIT, WM_SETTEXT, (WPARAM)0, (LPARAM)szText);
						}

						// Update the screen
						if (bVidOkay) {
							VidPaint(0);
						}
					}
					break;
				}
			}
			break;
		}

		case WM_CLOSE:
			if (nExitStatus != 1) {
				fVidScreenAngle = fPrevScreenAngle;
				fVidScreenCurvature = fPrevScreenCurvature;
			}
			EndDialog(hDlg, 0);
			break;
	}

	return 0;
}

void ScreenAngleDialog()
{
	FBADialogBox(hAppInst, MAKEINTRESOURCE(IDD_SCREENANGLE), hScrnWnd, (DLGPROC)ScreenAngleProc);
}

// -----------------------------------------------------------------------------
// CPU clock dialog

static INT_PTR CALLBACK CPUClockProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM)	// LPARAM lParam
{
	switch (Msg) {
		case WM_INITDIALOG: {
			TCHAR szText[16];
			nExitStatus = 0;

			WndInMid(hDlg, hScrnWnd);

			// Initialise slider
			SendDlgItemMessage(hDlg, IDC_CPUCLOCK_SLIDER, TBM_SETRANGE, (WPARAM)0, (LPARAM)MAKELONG(0x80, 0x0200));
			SendDlgItemMessage(hDlg, IDC_CPUCLOCK_SLIDER, TBM_SETLINESIZE, (WPARAM)0, (LPARAM)0x05);
			SendDlgItemMessage(hDlg, IDC_CPUCLOCK_SLIDER, TBM_SETPAGESIZE, (WPARAM)0, (LPARAM)0x10);
			SendDlgItemMessage(hDlg, IDC_CPUCLOCK_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)0x0100);
			SendDlgItemMessage(hDlg, IDC_CPUCLOCK_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)0x0120);
			SendDlgItemMessage(hDlg, IDC_CPUCLOCK_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)0x0140);
			SendDlgItemMessage(hDlg, IDC_CPUCLOCK_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)0x0180);

			// Set slider to current value
			SendDlgItemMessage(hDlg, IDC_CPUCLOCK_SLIDER, TBM_SETPOS, (WPARAM)true, (LPARAM)nBurnCPUSpeedAdjust);

			// Set the edit control to current value
			_stprintf(szText, _T("%i"), (int)((double)nBurnCPUSpeedAdjust * 100 / 256 + 0.5));
			SendDlgItemMessage(hDlg, IDC_CPUCLOCK_EDIT, WM_SETTEXT, (WPARAM)0, (LPARAM)szText);

			return TRUE;
		}
		case WM_COMMAND: {
			switch (HIWORD(wParam)) {
				case BN_CLICKED: {
					if (LOWORD(wParam) == IDOK) {
						nExitStatus = 1;
						SendMessage(hDlg, WM_CLOSE, 0, 0);
					}
					if (LOWORD(wParam) == IDCANCEL) {
						nExitStatus = -1;
						SendMessage(hDlg, WM_CLOSE, 0, 0);
					}
					break;
				}
				case EN_UPDATE: {
					if (nExitStatus == 0) {
						TCHAR szText[16] = _T("");
						bool bValid = 1;
						int nValue;

						if (SendDlgItemMessage(hDlg, IDC_CPUCLOCK_EDIT, WM_GETTEXTLENGTH, (WPARAM)0, (LPARAM)0) < 16) {
							SendDlgItemMessage(hDlg, IDC_CPUCLOCK_EDIT, WM_GETTEXT, (WPARAM)16, (LPARAM)szText);
						}

						// Scan string in the edit control for illegal characters
						for (int i = 0; szText[i]; i++) {
							if (!_istdigit(szText[i])) {
								bValid = 0;
								break;
							}
						}

						if (bValid) {
							nValue = _tcstol(szText, NULL, 0);
							if (nValue < 1) {
								nValue = 1;
							} else {
								if (nValue > 400) {
									nValue = 400;
								}
							}

							nValue = (int)((double)nValue * 256.0 / 100.0 + 0.5);

							// Set slider to current value
							SendDlgItemMessage(hDlg, IDC_CPUCLOCK_SLIDER, TBM_SETPOS, (WPARAM)true, (LPARAM)nValue);
						}
					}
					break;
				}
			}
			break;
		}

		case WM_HSCROLL: {
			switch (LOWORD(wParam)) {
				case TB_BOTTOM:
				case TB_ENDTRACK:
				case TB_LINEDOWN:
				case TB_LINEUP:
				case TB_PAGEDOWN:
				case TB_PAGEUP:
				case TB_THUMBPOSITION:
				case TB_THUMBTRACK:
				case TB_TOP: {
					if (nExitStatus == 0) {
						TCHAR szText[16];
						int nValue;

						// Update the contents of the edit control
						nValue = SendDlgItemMessage(hDlg, IDC_CPUCLOCK_SLIDER, TBM_GETPOS, (WPARAM)0, (LPARAM)0);
						nValue = (int)((double)nValue * 100.0 / 256.0 + 0.5);
						_stprintf(szText, _T("%i"), nValue);
						SendDlgItemMessage(hDlg, IDC_CPUCLOCK_EDIT, WM_SETTEXT, (WPARAM)0, (LPARAM)szText);
					}
					break;
				}
			}
			break;
		}

		case WM_CLOSE:
			if (nExitStatus == 1) {
				TCHAR szText[16] = _T("");

				SendDlgItemMessage(hDlg, IDC_CPUCLOCK_EDIT, WM_GETTEXT, (WPARAM)16, (LPARAM)szText);
				nBurnCPUSpeedAdjust = _tcstol(szText, NULL, 0);
				if (nBurnCPUSpeedAdjust < 1) {
					nBurnCPUSpeedAdjust = 1;
				} else {
					if (nBurnCPUSpeedAdjust > 400) {
						nBurnCPUSpeedAdjust = 400;
					}
				}

				nBurnCPUSpeedAdjust = (int)((double)nBurnCPUSpeedAdjust * 256.0 / 100.0 + 0.5);
			}
			EndDialog(hDlg, 0);
			break;
	}

	return 0;
}

void CPUClockDialog()
{
	FBADialogBox(hAppInst, MAKEINTRESOURCE(IDD_CPUCLOCK), hScrnWnd, (DLGPROC)CPUClockProc);
}

// -----------------------------------------------------------------------------
// Cubic filter quality dialog

static INT_PTR CALLBACK CubicProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM)	// LPARAM lParam
{
	static double dPrevB, dPrevC;

	switch (Msg) {
		case WM_INITDIALOG: {
			TCHAR szText[16];
			dPrevB = dVidCubicB;
			dPrevC = dVidCubicC;
			nExitStatus = 0;

			WndInMid(hDlg, hScrnWnd);

			// Initialise slider
			SendDlgItemMessage(hDlg, IDC_SCANLINE_SLIDER, TBM_SETRANGE, (WPARAM)0, (LPARAM)MAKELONG(0, 10000));
			SendDlgItemMessage(hDlg, IDC_SCANLINE_SLIDER, TBM_SETLINESIZE, (WPARAM)0, (LPARAM)100);
			SendDlgItemMessage(hDlg, IDC_SCANLINE_SLIDER, TBM_SETPAGESIZE, (WPARAM)0, (LPARAM)500);
			SendDlgItemMessage(hDlg, IDC_SCANLINE_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)3333);
			SendDlgItemMessage(hDlg, IDC_SCANLINE_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)5000);
			SendDlgItemMessage(hDlg, IDC_SCANLINE_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)7500);

			// Set slider to current value
			SendDlgItemMessage(hDlg, IDC_SCANLINE_SLIDER, TBM_SETPOS, (WPARAM)true, (LPARAM)((1.0 - dVidCubicB) * 10000));

			// Set the edit control to current value
			_stprintf(szText, _T("%.3lf"), 1.0 - dVidCubicB);
			SendDlgItemMessage(hDlg, IDC_SCANLINE_EDIT, WM_SETTEXT, (WPARAM)0, (LPARAM)szText);

			SetWindowText(hDlg, FBALoadStringEx(hAppInst, IDS_NUMDIAL_FILTER_SHARP, true));

			// Update the screen
			if (bDrvOkay) {
				VidPaint(2);
			}

			return TRUE;
		}
		case WM_COMMAND: {
			switch (HIWORD(wParam)) {
				case BN_CLICKED: {
					if (LOWORD(wParam) == IDOK) {
						nExitStatus = 1;
						SendMessage(hDlg, WM_CLOSE, 0, 0);
					}
					if (LOWORD(wParam) == IDCANCEL) {
						nExitStatus = -1;
						SendMessage(hDlg, WM_CLOSE, 0, 0);
					}
					break;
				}
				case EN_UPDATE: {
					if (nExitStatus == 0) {
						TCHAR szText[16] = _T("");
						bool bPoint = 0;
						bool bValid = 1;

						if (SendDlgItemMessage(hDlg, IDC_SCANLINE_EDIT, WM_GETTEXTLENGTH, (WPARAM)0, (LPARAM)0) < 16) {
							SendDlgItemMessage(hDlg, IDC_SCANLINE_EDIT, WM_GETTEXT, (WPARAM)16, (LPARAM)szText);
						}

						// Scan string in the edit control for illegal characters
						for (int i = 0; szText[i]; i++) {
							if (szText[i] == _T('.')) {
								if (bPoint) {
									bValid = 0;
									break;
								}
							} else {
								if (!_istdigit(szText[i])) {
									bValid = 0;
									break;
								}
							}
						}

						if (bValid) {
							dVidCubicB = 1.0 - _tcstod(szText, NULL);
							if (dVidCubicB < 0.0) {
								dVidCubicB = 0.0;
							} else {
								if (dVidCubicB > 1.0) {
									dVidCubicB = 1.0;
								}
							}

							// Set slider to current value
							SendDlgItemMessage(hDlg, IDC_SCANLINE_SLIDER, TBM_SETPOS, (WPARAM)true, (LPARAM)((1.0 - dVidCubicB) * 10000));

							// Update the screen
							if (bVidOkay) {
								VidPaint(2);
							}
						}
					}
					break;
				}
			}
			break;
		}

		case WM_HSCROLL: {
			switch (LOWORD(wParam)) {
				case TB_BOTTOM:
				case TB_ENDTRACK:
				case TB_LINEDOWN:
				case TB_LINEUP:
				case TB_PAGEDOWN:
				case TB_PAGEUP:
				case TB_THUMBPOSITION:
				case TB_THUMBTRACK:
				case TB_TOP: {
					if (nExitStatus == 0) {
						TCHAR szText[16];

						// Update the contents of the edit control
						dVidCubicB = 1.0 - (double)SendDlgItemMessage(hDlg, IDC_SCANLINE_SLIDER, TBM_GETPOS, (WPARAM)0, (LPARAM)0) / 10000;
						_stprintf(szText, _T("%.3lf"), 1.0 - dVidCubicB);
						SendDlgItemMessage(hDlg, IDC_SCANLINE_EDIT, WM_SETTEXT, (WPARAM)0, (LPARAM)szText);

						// Update the screen
						if (bVidOkay) {
//							VidRedraw();
							VidPaint(2);
						}
					}
					break;
				}
			}
			break;
		}

		case WM_CLOSE:
			if (nExitStatus != 1) {
				dVidCubicB = dPrevB;
				dVidCubicC = dPrevC;
			}
			EndDialog(hDlg, 0);
			break;
	}

	return 0;
}

void CubicSharpnessDialog()
{
	FBADialogBox(hAppInst, MAKEINTRESOURCE(IDD_SCANLINE), hScrnWnd, (DLGPROC)CubicProc);
}

