Oksy
Гость
|
|
« : 18-03-2006 06:24 » |
|
Люди, помогите, если кто знает. Материал взят из книги Г.Шилдта(название не знаю):
Сохраниение части экрана Прерывание 16, функция 8 возвращает символ из текущей позиции курсора в AL и его атрибут в AH. Функция save_video(), показанная здесь, считывает часть экрана, сохраняет информацию в буфер, и очищает эту часть экрана.
void save_video(startx,endx,starty,endy,buf_ptr) int startx,endx,starty,endy; unsigned int *buf_ptr; { union REGS r; register int i,j;
for(i=starty;i for(j=startx;j goto_xy(j,i); r.h.ah=8; /* функция чтения символа */ r.h.bh=0; /* видео страница */ *buf_ptr++ = int86(0x10,&r,&r); putchar(' '); /* очистка экрана */ } }
Восстановление экрана Восстановление экрана после сделанного выбора из меню, заключается просто в записи предварительно запомненной информации назад в видео память. Для того, чтобы сделать это, используйте прерывание 16, функцию 9, которая требует, чтобы символ был в AL, аттрибут в BL, видео страница в ВН, а количество записываемых символов в CX (в нашем случае 1). Функция restore_video(), описанная здесь, помещает информацию из буфера, на который указывает buf_ptr, на экран, заданный начальными и конечными координатами X и Y.
void restore_video(startx,endx,starty,endy,buf_ptr) int startx,endx,starty,endy; unsigned int *buf_ptr; { union REGS r; register int i,j;
for(i=starty;i for(j=startx;j goto_xy(j,i);>BR? r.h.ah=9; /* функция записи символа */ r.h.bh=0; /* видео страница */ r.x.cx=1; /* число повторений символа */ r.h.al=*buf_ptr++; /* символ */ r.h.bl=*buf_ptr++; /* атрибут */ *buf_ptr++ = int86(0x10,&r,&r); } }
Как я поняла, здесь используется "старомодный" стиль ситаксиса. Вопрос: как это будет выглядеть в стиле "модерн"? Пробовала преобразовать сама. Почти получилось, но функция restore_video(...) возвлащает на экран белиберду, скорее всего из-за непереведенного мной >BR? в функции restore_video(...), эта часть просто отсутствует в моем варианте. Кто знает, что это такое и как оно выглядит в "модерне"?
|
|
« Последнее редактирование: 13-12-2007 20:59 от Алексей1153++ »
|
Записан
|
|
|
|
Oksy
Гость
|
|
« Ответ #1 : 18-03-2006 08:49 » |
|
Так выглядит мой вариант: #include <dos.h> #include <conio.h> #include <stdio.h> void save_video(int x1, int y1, int x2, int y2, unsigned int *buf) { union REGS r; register int i, j; for(i=y1;i<y2;i++) { for(j=x1;j<x2;j++) { gotoxy(j,i); r.h.ah=8; r.h.bh=1; *buf++=int86(0x10,&r,&r); putchar(' '); } } }
void restore_video(int x1, int y1, int x2, int y2, unsigned int *buf) { union REGS r; register int i, j; for(i=y1;i<y2;i++) { for(j=x1;j<x2;j++) { gotoxy(j,i); r.h.ah=9; r.h.bh=0; r.x.cx=1; r.h.al=*buf++; r.h.bl=*buf++; *buf++=int86(0x10,&r,&r); } } }
void main() { clrscr(); _setcursortype(_NOCURSOR); int i=0; for(i; i<=2078; i++) printf("0"); unsigned int *buf; getch(); save_video(10,5,13,8,buf); getch(); restore_video(1,1,4,4,buf); getch(); }
|
|
« Последнее редактирование: 13-12-2007 20:59 от Алексей1153++ »
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #2 : 18-03-2006 11:42 » |
|
for(i=starty;i for(j=startx;j goto_xy(j,i); r.h.ah=8; /* функция чтения символа */ r.h.bh=0; /* видео страница */ *buf_ptr++ = int86(0x10,&r,&r); putchar(' '); /* очистка экрана */ } } Здесь же синтаксическая ошибка. Не верю, чтобы работало. Так циклы отродясь (языка C) не писались. Далее по сути задачи. Можно, конечно, использовать прерывание 10h (видео в BIOS), но "белые" люди со времён распространения CGA и более развитых адаптеров работают напрямую с видеопамятью. Для цветного текстового режима видеопамять экрана начинается по адресу B800h:0000h. Каждый символ описывается двумя байтами: первый байт - ASCII код символа, второй байт - цветовой атрибут (тот, что устанавливается функцией textattr - в помощи Turbo C описано, как им пользоваться). Такими парами байтов описывается весь экран построчно от левого верхнего угла. Т.е. первые 160 байт описывают символы первой строки экрана, вторые 160 байт - вторую строку и т.д. Всего для обычного текстового режима используется 80*25*2=4000 байт. Соответственно, несложными арифметическими преобразованиями можно получить адрес конкретного знакоместа и прочитать записанный там символ и его цвет. Можно осуществлять и запись. Поищу примеры...
|
|
« Последнее редактирование: 13-12-2007 21:00 от Алексей1153++ »
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
nikedeforest
|
|
« Ответ #3 : 18-03-2006 12:39 » |
|
Вот пример реализации функции putpixel. В файле отчет по лабораторной и текст программы. Вроде там должно быть все понятно. P.S. Прошу особо не придираться, это я достал лабораторную со второго курса .
|
|
|
Записан
|
ещё один вопрос ...
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #4 : 18-03-2006 13:09 » |
|
Примеров не нашёл, поэтому сам собрал программку. #include <conio.h> #include <dos.h> #include <stdlib.h>
/* ОПРЕДЕЛЕНИЕ ВИДЕОПАМЯТИ */
/* Структура знакоместа в видеопамяти */ struct videochar { char ascii; /* ASCII код символа */ char color; /* цветовой атрибут символа */ };
/* Определение типа видеопамяти */ typedef struct videochar far *videomem;
/* Адресация переменной video таким образом, чтобы через эту переменную можно было обращаться к видеопамяти */ videomem video = (videomem)MK_FP(0xB800, 0);
/* ФУНКЦИИ РАБОТЫ С ВИДЕОПАМЯТЬЮ */
/* Получает указатель на знакоместо в видеопамяти, находящееся в позиции x, y */ videomem get_vidchptr(int x, int y) { /* Перемещаем указатель на строку y - отсчитываем y-1 раз по 80 знакомест */ /* Затем перемещаемся в столбец x - отсчитываем x-1 знакоместо */ return video + (y - 1) * 80 + (x - 1); }
/* Сохранение куска изображения в буфер */ void save_video(int x1, int y1, int x2, int y2, struct videochar **buffer) { int x, y; struct videochar *iter; /* Определяем, сколько нам нужно памяти для буфера */ size_t bufsize = (y2 - y1 + 1) * (x2 - x1 + 1) * sizeof(struct videochar); /* Выделяем память под буфер */ *buffer = (struct videochar *)malloc(bufsize); /* Чтобы не потерять указатель на начало буфера, пользуемся вспомогательным указателем. */ iter = *buffer; for(x = x1; x <= x2; ++x) for(y = y1; y <= y2; ++y, iter++) /* Копируем знакоместо из видепамяти в буфер */ *iter = *get_vidchptr(x, y); }
/* Восстановление куска изображения из буфера */ void restore_video(int x1, int y1, int x2, int y2, struct videochar **buffer) { int x, y; struct videochar *iter; /* Чтобы не потерять указатель на начало буфера, пользуемся вспомогательным указателем. */ iter = *buffer; for(x = x1; x <= x2; ++x) for(y = y1; y <= y2; ++y, iter++) /* Копируем знакоместо из буфера в видепамять */ *get_vidchptr(x, y) = *iter; /* Освобождаем память буфера */ free(*buffer); }
/* ОСНОВНАЯ ПРОГРАММА */
int main() { struct videochar *buffer; /* Перед запуском заполните чем-нибудь экран для наглядности. */ getch(); /* Запоминаем кусок экрана между 10 и 70 столбцами и 10 и 20 строками */ save_video(10, 10, 70, 20, &buffer); /* Очищаем экран - убеждаемся, что картинки нет */ clrscr(); getch(); /* Восстанавливаем кусок экрана - убеждаемся, что всё работает */ restore_video(10, 10, 70, 20, &buffer); getch(); return 0; } Обращаю внимание, что в программе нет проверок при работе с памятью. Это означает, что: - перед сохранением буфер ничего не содержит, иначе будет утечка памяти; - оперативной памяти на буфер всегда хватает - факт выделения не проверяется - иначе будет ошибка; - видеопамять в самом деле начинается с B800:0000, т.е не какой-нибудь там монохромный Hercules 20-илетней давности; - размер восстанавливаемого изображения совпадает с размером сохраняемого, иначе могут быть ошибки. Последний случай можно обойти, используя такую структуру видеобуфера: struct videobuffer { int x1, y1, x2, y2; struct videochar *buffer; };
т.е. чтобы размеры и позиция сохранялись вместе с видеобуфером и случайно не потерялись бы где-нибудь в недрах программы, тогда при восстановлении не нужно будет передавать координаты области восстановления.
|
|
« Последнее редактирование: 07-04-2006 05:34 от dimka »
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #5 : 18-03-2006 13:17 » |
|
Вот ведь... Чего было мучаться...
в conio.h есть функции gettext и puttext - они делают всё, что нужно.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
nikedeforest
|
|
« Ответ #6 : 18-03-2006 13:25 » |
|
Будем надеяться не напрасно ты мучался, ведь возможно для Oksy важно поработать с видеопамятью напрямую.
|
|
|
Записан
|
ещё один вопрос ...
|
|
|
PooH
Глобальный модератор
Offline
Пол:
... и можно без хлеба!
|
|
« Ответ #7 : 18-03-2006 15:15 » |
|
for(i=starty;i for(j=startx;j goto_xy(j,i);>BR? скорее всего книга в HTML и СИ-шнуй знак "<" воспринялся как открытие HTML-тэга
|
|
|
Записан
|
Удачного всем кодинга! -=x[PooH]x=-
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #8 : 18-03-2006 16:51 » |
|
Будем надеяться не напрасно ты мучался, ведь возможно для Oksy важно поработать с видеопамятью напрямую. Это врядли. Если только "для общего развития", но совсем не для решения задачи. К тому же gettext и puttext и так работают с видеопамятью напрямую (если directvideo включено, иначе через BIOS).
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
Oksy
Гость
|
|
« Ответ #9 : 19-03-2006 07:16 » |
|
dimka, спасибо за подробный ликбез!:) Как разгребусь с дипломом, сразу же займусь "общим развитием"
|
|
|
Записан
|
|
|
|
МАКСИМ.
Гость
|
|
« Ответ #10 : 06-04-2006 17:19 » |
|
привет !я тоже считал Шилдта и сталкнулся с проблемой функций Save_Video()и Restore_Video(). там с предачей аттрибута байта в функцию. у меня так получилось в BORLAND C 3.1 c этими функциями: /*------save screen-------*/ void Save_Video(int startx,int endx, int starty,int endy, unsigned int *buf_ptr){ union REGS r; register int i,j; for(i = starty;i<endy; i++) for(j = startx;j<endx; j++) { goto_xy(j,i); r.h.ah = 8; r.h.bh = 0; *buf_ptr++ = int86(0x10,&r,&r); putchar(' ');//clear screen } } /*-----return of screen-----*/ void Restore_Video(int startx,int endx, int starty,int endy, unsigned int *buf_ptr){ union REGS r; register int i,j; for( i=starty; i<endy; i++) for( j=startx; j<endx; j++){ goto_xy(j,i); r.h.ah = 9;//func write simbol r.h.bh = 0;//videopage r.x.cx = 1;// 1 simbol r.h.al = *buf_ptr++; r.h.bl = 0x90;// !!! attrib - цвет фона(9) и цвет символа(0) я задал сам; int86(0x10,&r,&r);// ! } } с синтаксисом в стиле "модерн" я немного не понял что имелось ввиду. это программирование на Си под виндос?
|
|
« Последнее редактирование: 13-12-2007 21:01 от Алексей1153++ »
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #11 : 06-04-2006 19:50 » |
|
МАКСИМ., В виндовсе практически нельзя напрямую лазить в видеопамять. Так что, покажи не понятный участок кода. Будем разбираться и объяснять.
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
МАКСИМ.
Гость
|
|
« Ответ #12 : 07-04-2006 01:28 » |
|
Finch, я через функции BIOS-а только начал работать с видеопамятью.а про функции(Save_Video()и Restore_Video() ) что я писал - я их реализовал в своих программах. я в DOs-е пишу программки.до винды еще не дошел.но немного программировал на делфи, ассемблере в винде. А вообще программировать хочу научиться и перенять некоторый опыт от профессионалов.сейчас и я изучаю Си и по возможности Ассемблер.
|
|
|
Записан
|
|
|
|
|