Программирование и кодирование
return(0); /*всегда завершается успешно*/
}
/*
Возвращает адрес сегмента вектора прерываний "intno"
*/
unsigned int get_int_seg(intno)
int intno;
{
union REGS regs;
struct SREGS segregs;
regs.h.al = (unsigned char) intno;
regs.h.ah = 0x35; /*функция "Получить вектор" DOS*/
intdosx(®s, ®s, &segregs);
return((unsigned) segregs.es);
}
-------------------------------------------------------------------
Листинг 7-8. SNAPSHOT.C
-------------------------------------------------------------------
/*
Наименование: SNAPSHOT.C
Назначение: утилита, остающаяся резидентно в памяти после
завершения, для сохранения образов текстовых
экранов в pасшиpенной памяти.
*/
#include
#include
#include
#include
#include
#include "emmconst.h" /*константы менеджеpа pасшиpенной памяти*/
#include "emmtypes.h" /*структуры данных менеджеpа pасшиpенной па-
мяти*/
#include "emmerr.h" /*коды ошибок менеджеpа pасшиpенной памяти*/
- 7-76 -
#include "emmfunc.h" /*объявления функций менеджеpа pасшиpенной
памяти*/
#define PRTSC_INT 5 /*прерывание печати экрана*/
#define HANDLE_NAME "SNAPSHOT" /*имя обpаботчика pасшиpен-
ной памяти*/
#define MAX_SCR 500 /*максимальное кол-во сохра-
няемых экранов*/
#define MDA_SEG 0xB000 /*сегмент буфера адаптера
монохромного дисплея*/
#define CGA_SEG 0xB800 /*сегмент буфера адаптера
цветного графического дисплея*/
#define SCR_ROWS 25 /*предполагается 25 строк -
процедура должна определить*/
/*фактическое кол-во строк
зависит от адаптера*/
#pragma pack(1) /*структура данных, выровненная по байтам*/
#define DisplayError(rc) ShowEMMErr(rc, __LINE__, __FILE__)
typedef struct bios_video_data { /*базисные видеоданные BIOS*/
unsigned char crt_mode; /*режим дисплея*/
unsigned int crt_cols; /*кол-во колонок на экране*/
unsigned int crt_len; /*длина буфера регенерации в
байтах*/
unsigned int crt_start; /*начальный адрес в буфере
регенерации*/
unsigned int cursor_pos[8]; /*положение курсора для 8
страниц*/
unsigned int cursor_mode; /*текущая установка режима
курсора*/
unsigned char active_page; /*текущая отображаемая стра-
ница*/
unsigned int addr_6845; /*адрес базы активной платы
отображения*/
unsigned char crt_mode_set; /*текущая установка регистра
3х8*/
unsigned char crt_palette; /*текущая установка палитры
- цветная плата*/
} BIOS_VIDEO_DATA;
typedef struct scr { /*дескриптор данных экрана*/
unsigned int scr_page; /*начальная страница pасши-
pенной памяти для экранов*/
unsigned int scr_offset; /*начальное смещение расши-
ренной памяти для экранов*/
unsigned int scr_width; /*кол-во колонок на экране*/
unsigned int scr_len; /*длина экрана в байтах*/
} SCR;
typedef struct scr_index { /*индексная структура экрана*/
void (interrupt far *scr_int5)(); /*указатель на нашу програм-
му обслуживания прерывания*/
unsigned int scr_count; /*кол-во экранов, сохранен-
ных в текущий момент*/
unsigned int scr_max; /*максимальное кол-во экранов
- 7-77 -
для сохранения*/
} SCR_INDEX;
/*
глобальные данные
*/
void (interrupt far *old_int5)(); /*старый вектор печати экрана*/
PMAP *emm_save; /*указатель на область сохране-
ния контекста менеджеpа pасшиpенной памяти*/
unsigned int emm_tpages, /*общее кол-во страниц pасши-
pенной памяти*/
emm_apages, /*доступное кол-во страниц
pасшиpенной памяти*/
emm_handle, /*обpаботчик pасшиpенной памя-
ти*/
emm_pages, /*кол-во страниц, принадлежащих
обpаботчику*/
isr_status, /*0: isr следует сцепить,
<>0: isr следует обслужить*/
terminate_flag; /*1: закончить эту программу*/
char far *page_frame; /*удаленная -> в кадровый буфер*/
SCR_INDEX far *ip; /*удаленная -> в индекс экрана*/
SCR far *sp; /*удаленная -> в дескриптор экрана*/
BIOS_VIDEO_DATA far *vp = (BIOS_VIDEO_DATA far *) 0x00400049L;
/*удаленная -> в область видео дан-
ных BIOS*/
MOVE_XCHG mcb; /*структура передвижения/обмена
областей*/
#pragma check_stack(off)
/*очищается, если "control-c"*/
void break_handler(sig_type)
int sig_type;
{
signal(SIGINT, SIG_IGN); /*запрещает "control-c" во время
драйвера*/
cleanup;
exit(0);
}
/*
драйвер прерывания для прерывания печати экрана
Делает моментальный снимок обычной памяти в
pасшиpенную память
*/
void interrupt cdecl far int5_isr(es,ds,di,si,bp,sp,bx,dx,cx,ax,ip,
cs,flags)
unsigned es,ds,di,si,bp,sp,bx,dx,cx,ax,ip,cs,flags;
{
static int rc = 0; /*отслеживается последний код
возврата*/
int status;
if (!isr_status) /*если обслуживание прерывания
не активизировано, подцепить к
предыдущему драйверу прерывания*/
- 7-78 -
_chain_intr(old_int5);
if (rc == 0) { /*продолжать только, если ранее не
было ошибок*/
rc = EMSGetPageMap(emm_save);
if (rc == 0) { /*контекст сохранен успешно*/
/*сделать снимок экрана*/
rc = dump_screen();
/*восстановить контекст предыдущего отображения*/
if (status = EMSSetPageMap(emm_save))
rc = status; /*обновить код ошибки*/
}
}
/*если произошла какая-либо ошибка, объявить вслух*/
if (rc)
Beep(32000);
}
dump_screen()
{
int rc;
unsigned int overflow, new_offset, scr_size;
/*отобразить индексные данные экрана в логической странице
0 в физическую страницу 0*/
if (rc = EMSMapHandlePage(emm_handle, 0, 0))
return(rc); /*отказ*/
/*убедитесь, что не вышли из индексных элементов*/
if (ip->scr_count >= ip->scr_max)
return(1); /*переполнение индекса*/
/*если экран переполняет страницу, разместите одну или более
дополнительных страниц*/
scr_size = vp->crt_cols * SCR_ROWS * 2; /*кол-во байтов в
экране*/
new_offset = sp->scr_offset + scr_size; /*новое смещение
в буфере сохранения*/
if (new_offset > PAGE_SIZE) { /*экран переполняет страницу*/
overflow = new_offset - PAGE_SIZE; /*величина переполне-
ния страницы*/
emm_pages += (overflow / PAGE_SIZE); /*кол-во необходимых
дополнительных страниц*/
new_offset = overflow % PAGE_SIZE; /*размер добавочного
фрагмента*/
if (new_offset) /*прибавить страницу на добавок,*/
emm_pages++; /*если необходимо*/
if (rc = EMSReallocPages(emm_handle, &emm_pages))
- 7-79 -
return(rc); /*отказ*/
}
/*снимок, отображающий видеоэкран в расширенную память*/
mcb.region_length = (long) scr_size; /*кол-во байтов на экра-
mcb.source.memory_type = CONV_MEM; не в обычной памяти*/
mcb.source.handle = 0; /*никакой обpаботчик не исп-ся*/
mcb.source.initial_offset = vp->crt_start; /*начальное сме-
щение экрана*/
mcb.source.initial_seg_page = (vp->crt_mode == 7) ? MDA_SEG :
CGA_SEG;
/*работает только с цветным/монохромным текстом*/
mcb.dest.memory_type = EXP_MEM; /*идет в расши-
ренную память*/