#include <stdio.h>
#include <conio.h>
#include <dos.h>

// Описание функций
void	main(void);
int	SetPowerState( unsigned char );
int	GetPowerState( unsigned char* );
int	PowerCapabilities( unsigned char*, unsigned char*, unsigned char*);
int	AnalyseResult(union REGS);

#define ON	0x00
#define OFF	0x04
#define STANDBY	0x01
#define SUSPEND	0x02
#define REDUCED	0x08

//======================================================================
// Главная функция
//======================================================================
void main(void) {

	int 	uiResult;
	unsigned char 	ucMode, ucModes,
						ucMinorVer, ucMajorVer;

	// Определяем возможность управления энергопотреблением
	uiResult = PowerCapabilities( &ucModes, &ucMajorVer, &ucMinorVer );

	printf("\n\n Copyright (C)Frolov G.V.,1995. E-mail: frolov@glas.apc.org\n");

	if(uiResult==0) {
		printf("\n Версия VBE Power Management %d.%d",
				(int)ucMajorVer, (int)ucMinorVer );

		printf("\n Поддерживаются режимы:\n"
				"STANDBY - %s\n"
				"SUSPEND - %s\n"
				"OFF - %s\n"
				"REDUCED - %s\n",
				(ucModes & STANDBY)?	"да" : "нет",
				(ucModes & SUSPEND)?	"да" : "нет",
				(ucModes & OFF)?		"да" : "нет",
				(ucModes & REDUCED)?	"да" : "нет"
		);
	}

	else if(uiResult < 0) {
		printf("\n Возможность управления энергопотреблением не поддерживается" );
		return;
	}

	else if(uiResult > 0) {
		printf("\n Ошибка при вызове функции VBE Power Management" );
		return;
	}

	// Определяем текущий режим
	uiResult = GetPowerState( &ucMode );
	printf("\n Функция GetPowerState возвращает %d", uiResult );
	printf("\n GetPowerState = %x", ucMode );

	printf("\n Текущий режим: %s\n",
		(ucMode & STANDBY)	?	"STANDBY" :
		(ucMode & SUSPEND)	?	"SUSPEND" :
		(ucMode & OFF)			?	"OFF" :
		(ucMode & REDUCED)	?	"REDUCED" : "Неопределен"
	);

	printf("\n\n После нажатия на клавиатуру гасим изображение (режим STANDBY)"
			 "\n Для продолжения работы нажмите любую клавишу"	);

	// Ожидаем нажатие на клавиатуру
	getch();

	// Гасим экран монитора
	uiResult = SetPowerState( STANDBY );
	printf("\n Функция SetPowerState( STANDBY ) возвращает %d", uiResult );

	// Ожидаем нажатие на клавиатуру
	getch();

	// Включаем монитор
	uiResult = SetPowerState( ON );
	printf("\n Функция SetPowerState( ON ) возвращает %d", uiResult );

	return;
}

//=================================================
// Функция SetPowerState
// Устанавливает режим видеоадаптера и монитора
//=================================================
int
SetPowerState( unsigned char ucMode )
{
	union REGS regs;
	int	iResult;

	regs.h.ah = 0x4f;
	regs.h.al = 0x10;
	regs.h.bl = 0x01;
	regs.h.bh = ucMode;
	int86(0x10, &regs, &regs);

	iResult = AnalyseResult(regs);

	return iResult;
}

//=================================================
// Функция GetPowerState
// Определят текущий режим видеоадаптера
//=================================================
int
GetPowerState( unsigned char *ucMode )
{
	union REGS regs;
	int	iResult;

	regs.h.ah = 0x4f;
	regs.h.al = 0x10;
	regs.h.bl = 0x02;

	int86(0x10, &regs, &regs);

	*ucMode = regs.h.bh;

	iResult = AnalyseResult(regs);

	return iResult;
}

//=================================================
// Функция PowerCapabilities
// Определяет возможности видеоподсистемы
//=================================================
int
PowerCapabilities( unsigned char *ucModes,
						 unsigned char *ucMajorVer,
						 unsigned char *ucMinorVer)
{
	union REGS regs;
	struct SREGS segregs;
	int	iResult;

	regs.h.ah = 0x4f;
	regs.h.al = 0x10;
	regs.h.bl = 0x00;

	segregs.es = 0x00;
	regs.x.di = 0x00;

	int86x(0x10, &regs, &regs, &segregs);

	*ucModes = regs.h.bh;
	*ucMinorVer = regs.h.bl & 0x0F; // Младший
	*ucMajorVer = (regs.h.bl & 0xF0) >> 4; // Старший

	iResult = AnalyseResult(regs);

	return iResult;
}

//=================================================
// Функция AnalyseResult
// Анализирует результат, возвращаемый функциями
// Power VBE
//=================================================
int
AnalyseResult(union REGS regs)
{
	int	iResult;

	// Функция VBE Power Management завершилась успешно
	if((regs.h.al == 0x4f) && (regs.h.ah == 0))
		iResult = 0;

	//
	else if(regs.h.al != 0x4f)
		iResult = -1;

	//
	else
		iResult = 1;

	return iResult;
}
