Aspect
#08
07 апреля 1998 |
|
Программирование - Вывод 64 символов в строке.
ЧТОБЫ СТРОКА ВМЕЩАЛА БОЛЬШЕ... Наверноe многие из вас сталкивались с нехваткой места в строке для вывода информации: в строке умещалось 32 символа стандартного фонта (8*8). No проблемa эта относительно легко разрешима. В принципе, можно выводить до 80 символов в строке. Своеобразными стандартами, что ли, в данной области являются 64 и 42 символа в строке (80 символов в строке используются редко, т.к. даже на хорошем мониторе разобрать текст становится затруднительно). Итак, начну, пожалуй, с 64 символов. При выводе в 64 символа в строке в каждый байт помещается по два символа 64-го фонта(против одного байта 32-го), следовательно символ 64-го фонта должен иметь размеры 4*8, т.к. в высоту он такой же как и его 32-ой собрат(фактически же, символ задается матрицей 3*7, т.к. справа и снизу должно быть свободное место, иначе вместо текста мы увидим абстрактную картину). Можно задать фонт стандартно: один символ - 8 байт, т.е. весь фонт (все 256 символов) займет 2048 байт, однако можно уменьшить его размеры в два раза, если задействовать пустое место. Тогда фонт будет выглядеть так: 2 символа 8 байтов, и фонт займет лишь 1024 байта, однако выводить его будет сложнее. Итак, прикинем: надо вывести символ на экран, при длине строки в 64 символа и ужатом фонте(т.е. фонте в 1024 байта). Для этого надо : 1. Вычислить адрес символа в фонте 2. Вычислить адрес вывода 3. Вывести символ 1. Адрес вычисляется довольно просто: делим код символа на два, находим адрес сдвоенной матрицы, далее проверяем на четность код символа (который был до деления) - если четный, то левая половинка байта, если нечетный - правая. 2. Адрес вывода берем из таблицы 3. Данный этап целесообразно разбить на две части, в зависимости от того, в какую половинку байта на экране мы будем выводить символ: а) Для левой половинки. Нечетный символ - никуда не двигаем, берем байт по адресу вывода, объединяем по логическому "и" (AND с маской %00001111 - то что справа, нам менять не стоит. Берем байт из матрицы символов, объединяем по AND с %11110000, объединяем по логическому "или" (OR) с тем что получили раньше, и "кладем" на экран. Четный символ - надо объединить по AND с %00001111, сдвинуть влево на 4, проделать то же с байтом адреса вывода, что и для четного объединить по OR с предыдущим результатом, и "положить" на экран. б) Для правой половинки. Тоже что и для левой, только надо будет сдвигать левую часть направо, и маска для экранной области будет %11110000. Ну вот, "загрузил" я вас запутанной теорией, пора бы ее подкрепить практикой. В качестве примера будет процедурка выводящая 64-ым шрифтом текст. 0RG #61A8 LD HL,TABLE ;заполняем таблицу LD DE,0 LD B,24 CALL ZAPTAB LD HL,TЕXT ;адрес текста в HL LD BC,0 ;B - Y,C - X координта ; в текстовых значениях WR_64 PUSH IX ;он нам еще пригодится WR_64R PUSH BC LD A,B ;смещение в таблице ADD A,A ADD A,A ADD A,A LD E,A LD D,0 LD IX,TABLE ;находим адрес, по ко- ;торому находится адрес ;вывода. ADD IX,DE ADD IX,DE WR_641 LD A,(HL) ;берем символ INC HL AND A ;ноль - конец текста JR Z,OUTBTEN CP 22 ;команда AT JR Z,WR_6471 CP #0D ;перевод строки JR Z,WR_64OL CALL PS_64 ;вывод левой половинки WR_64N LD A,(HL) ;берем следующий символ INC HL AND A ;аналогично JR Z,OUTBTEN CP 22 JR Z,WR_6471 CP #0D JR Z,WR_64OL CALL PR_64 ;вывод правой половинки INC C ;переход к следущему байту ;в строке на экране JR WR_641 ;и все по новой WR_64OL POP BC ;следущая строка INC B JR WR_64R OUTBTEN POP BC ;конец вывода POP IX RET WR_6471 POP BC ;переход к произвольной ;позиции вывода LD B,(HL) INC HL LD C,(HL) INC HL JR WR_64R ;ВЫВОД В ЛЕВУЮ ПОЛОВИНКУ БАЙТА ; A - КОД СИМВОЛА ; IX - ТАБЛИЦА АДРЕСОВ ВЫВОДА PS_64 PUSH HL ;то, что нужно - сохраняем PUSH IX LD L,A ;/2*8=*4 SRL L LD H,0 ADD HL,HL ADD HL,HL ADD HL,HL LD DE,FONT ADD HL,DE EX DE,HL ;в DE адрес матрицы символа SRL A ;проверка на четность LD B,8 ;8 байт выводить JR C,PS_642 ;нечет LD A,(IX) ;адрес вывода на экран LD H,(IX+1) PUSH BC ADD A,C LD L,A PS_641 LD A,(HL) ;мучаем байт с экрана AND #0F LD C,A LD A,(DE) ;мучаем выводимый байт AND #F0 OR C ;объединяем их LD (HL),A ;кладем на экран INC DE INC H DJNZ PS_641 ;повторяем POP BC POP IX POP HL RET PS_642 LD A,(IX) ;берем адрес вывода LD H,(IX+1) ADD A,C PUSH BC LD L,A PS_6422 LD A,(DE) ;выделяем правый кусок AND #0F RLA ;двигаем его влево RLA RLA RLA LD C,A LD A,(HL) ;а здесь все по-старому AND #0F OR C LD (HL),A INC DE INC H DJNZ PS_6422 POP BC POP IX POP HL RET ;ПРОЦЕДУРА ВЫВОДА В ПРАВУЮ ПОЛОВИНКУ ЭК- ;РАННОГО БАЙТА ;НА ВХОД В A - КОД СИМВОЛА ; В IX - ТАБЛИЦА АДРЕСОВ ВЫВОДА PR_64 PUSH HL ;ВСЕ АНАЛОГИЧНО ПРЕДЫУЩЕМУ ;СЛУЧАЮ PUSH IX PUSH BC LD L,A SRL L LD H,0 ADD HL,HL ADD HL,HL ADD HL,HL LD DE,FONT ADD HL,DE EX DE,HL SRL A LD B,8 JR C,PR_642 LD A,(IX) LD H,(IX+1) ADD A,C LD L,A PR_641 LD A,(HL) ;байт с экрана будем AND #F0 ;мучать LD C,A LD A,(DE) ;четный придется двигать SRL A SRL A SRL A SRL A OR C LD (HL),A ; а дальше все ясно INC DE INC H DJNZ PR_641 POP BC POP IX POP HL RET PR_642 LD A,(IX) LD H,(IX+1) ADD A,C LD L,A PR_6422 LD A,(HL) ; тут вроде все ясно AND #F0 LD C,A LD A,(DE) AND #0F OR C LD (HL),A INC DE INC H DJNZ PR_6422 POP BC POP IX POP HL RET ;процедура заполнения таблички ZAPTAB LD A,D LD C,A AND A DUP 3 RRCA EDUP AND #E0 ADD A,E EX AF,AF' LD A,C AND #18 OR #40 EX AF,AF' LD C,A EX AF,AF' DUP 8 LD (HL),C INC HL LD (HL),A INC A INC HL EDUP INC D DJNZ ZAPTAB EI RET ;выводимый текст TEXT DEFB "ПРИВЕТ ВСЕМ !!!",#0D,#0D DEFB "HELLO TO ALL!!!",0 ;здесь будет фонт FONT INCBIN "A:FONT48a.C" ;а здесь таблица адресов TABLE Эта процедура вывода занимает довольно много времени, ее можно заметно ускорить если сделать два набора символов: сдвинутый влево и сдвинутый вправо, при этом отпадает надобность что-то куда-то двигать: ORG #61A8 CALL RAZPAC ;превращаем один ужатый ;фонт в два разжатых LD HL,TABLE ;аналогично предыдущему LD DE,0 ;случаю LD B,24 CALL ZAPTAB LD HL,TEXT LD BC,0 LD IX,TABLE WR_64 PUSH IX WR_64R PUSH BC LD E,B LD D,0 LD IX,TABLE ADD IX,DE ADD IX,DE WR_641 LD A,(HL) INC HL AND A JR Z,OUTBTEN CP 22 JR Z,WR_6471 CP #0D JR Z,WR_64OL CALL PS_64 WR_64N LD A,(HL) INC HL AND A JR Z,OUTBTEN CP 22 JR Z,WR_6471 CP #0D JR Z,WR_64OL CALL PR_64 INC C JR WR_641 WR_64OL POP BC LD A,8 ADD A,B LD B,A JR WR_64R OUTBTEN POP BC POP IX RET WR_6471 LD B,(HL) INC HL LD C,(HL) INC HL JR WR_64R ;ВЫВОД В ЛЕВУЮ ПОЛОВИНКУ БАЙТА ; A - КОД СИМВОЛА ; IX - ТАБЛИЦА АДРЕСОВ ВЫВОДА PS_64 PUSH HL PUSH IX LD L,A ;делить на 2 не надо LD H,0 ADD HL,HL ADD HL,HL ADD HL,HL LD DE,FONTL ;левая половинка - ;левый фонт ADD HL,DE EX DE,HL LD A,(IX) LD H,(IX+1) PUSH BC ADD A,C LD L,A LD B,8 PS_641 LD A,(HL) ;ловкость рук и никаких AND #0F ;RRCA LD C,A LD A,(DE) OR C LD (HL),A INC DE INC H DJNZ PS_641 POP BC POP IX POP HL RET ;ПРОЦЕДУРА ВЫВОДА В ПРАВУЮ ПОЛОВИНКУ ЭК- ;РАННОГО БАЙТА ;НА ВХОД В A - КОД СИМВОЛА ; В IX - ТАБЛИЦА АДРЕСОВ ВЫВОДА PR_64 PUSH HL PUSH IX PUSH BC LD L,A LD H,0 ADD HL,HL ADD HL,HL ADD HL,HL LD DE,FONTR ;правая половинка - ADD HL,DE ;правый фонт EX DE,HL LD B,8 LD A,(IX) LD H,(IX+1) ADD A,C LD L,A PR_6422 LD A,(HL) ;и ничего не двигаем AND #F0 LD C,A LD A,(DE) OR C LD (HL),A INC DE INC H DJNZ PR_6422 POP BC POP IX POP HL RET ;ПРОЦЕДУРА РАЗЖИМАЮЩАЯ ФОНТ RAZPAC LD HL,FONT1 ;исходный фонт LD DE,FONTL ;левый фонт LD BC,#8000 ;128 символов в ужатом EXX ;фонте LD HL,FONTR ;правый фонт LD DE,FONTL+8 ;следующий символ LD BC,FONTR+8 ;следующий символ EXX RAZPAC2 LD C,8 ;а байт то в символе 8 ! RAZPAC1 LD A,(HL) ;начнем-с PUSH AF AND #F0 ;левый символ LD (DE),A INC DE EXX AND A ;двигаем DUP 4 RRCA EDUP LD (HL),A ;в правый фонт INC HL POP AF AND #F ;правый символ LD (BC),A ;в след. символ левого INC BC ;фонта DUP 4 ;двигаем RLCA EDUP LD (DE),A ; в след. символ правого INC DE ;фонта EXX INC HL DEC C JP NZ,RAZPAC1 ;разжимаем символ PUSH HL LD HL,8 ;переходим к следующему ADD HL,DE ;символу ужатого фонта EX DE,HL POP HL EXX LD HL,8 ADD HL,DE EX DE,HL LD HL,8 PUSH BC AND A ADC HL,BC LD C,L LD B,H POP HL EXX DJNZ RAZPAC2 RET ;ПРОЦЕДУРА ЗАПОЛНЯЮЩАЯ ТАБЛИЦУ ВЫВОДА ZAPTAB LD A,D LD C,A AND A DUP 3 RRCA EDUP AND #E0 ADD A,E EX AF,AF' LD A,C AND #18 OR #40 EX AF,AF' LD C,A EX AF,AF' DUP 8 LD (HL),C INC HL LD (HL),A INC A INC HL EDUP INC D DJNZ ZAPTAB EI RET TEXT DEFB "ПРИВЕТ ВСЕМ !!!",#0D,#0D DEFB "HELLO TO ALL!!!",0 TABLE FONT1 INCBIN "A:FONT48a.C" DEFS 1256 FONTL DEFS #800 FONTR DEFS #800 Способ, конечно, не экономичный, зато быстрый. Ну, с 64-ым фонтом разобрались, а о 42-ом фонте раскажу в следующий раз. (c)Trusov Ilya
Другие статьи номера:
Похожие статьи:
Warez - презентация игры Abe's Mission ("Миссия Эйба") - конверсия с PC - "Oddworld: Abe's Oddysee".
В этот день... 21 ноября