ZX Club
#07
28 февраля 1998 |
|
Coding - техника и алгоритмы демомейкинга: быстрый вывод графики через стек.
(C) Saruman / Dementia corp. Ну вот и прошло очередное demo-party, Enlight-97, и вновь вылило на головы бед- ных юзеров кучу крутейших и навороченней- ших демок. А бедный юзер сидит, глядит на них, и ничегошеньки-то ему не понятно: как вообще ТАКОЕ может быть возможно? А ведь возможно, и доказательство вот оно - перед глазами. Эта небольшая заметка, возможно, послужит началом для цикла статей, в которых я по- пытаюсь немного рассказать о демомейкинге, его техниках и алгоритмах. Я, конечно, не такой крутой кодер как Rst7, Max Iwamoto, Exploder и т.д., но о чем знаю - о том не- много расскажу. Я буду дико рад, если моя работа поможет написанию хоть одной отлич- ной проги. А поскольку начинать лучше все- го с самого начала, то сегодняшней темой будет Быстрый вывод графики через стек - Знаете, у меня на эк- ран выводится 300 спрайтов за одно пре- рывание, и я не могу избавиться от мерца- ния. Помогите! - Сейчас тебе кто-нибудь посоветует выводить их через стек. ;-) Из переписки в FIDO Возможно, читатель, внимательно следящий за всеми электронными изданиями, негодующе воскликнет: "Сколько можно об этом гово- рить ?!?!?" Сколько нужно! Раз еще появля- ются демы с дрожащими спрайтами и глючащи- ми эффектами (а они появляются!), значит, сказано еще недостаточно. Итак, основная идея, стоящая за данным методом, такова: ───────────────┬────────────────────── Команда │ Время исполнения ───────────────┼────────────────────── LD A,(reg) │ 7 LD (reg),A │ 7 INC reg │ 6 DEC reg │ 6 LD HL,(ADDR) │ 16 LD (ADDR),HL │ 16 POP reg │ 10 ! PUSH reg │ 11 ! LD SP,nnnn │ 10 ───────────────┴────────────────────── Итак, что мы видим? Для переброски двух байтов в нужное место у нас есть три пути: а) использовать регистр A. То есть имеем примерно такой кусок кода: LD A,(HL) LD (DE),A INC HL INC DE Итого 26*2=52 такта. Ouch... Многова- то! б) использовать регистровую пару HL: LD HL,(ADDR) LD (ADDR),HL Итого 16+16=32 такта плюс время на из- менение ADDR. То есть тоже немало... в) использовать операции PUSH и POP: LD SP,nnnn POP HL .... LD SP,nnnn PUSH HL .... Вы скажете: "Какой же это самый лучший способ, если он занимает аж 41 такт!!!" Но я не зря поставил в коде многоточия. Вспомните действие команд PUSH и POP: при PUSH происходит занесение значения из ре- гистра в адрес, содержащийся в SP, и уменьшение значения SP на 2; при POP - на- оборот, данные достаются из памяти, а SP увеличивается. А так как у нас имеется це- лых 10 регистровых пар, то мы можем уста- навливать стек только один раз для 20 байт. Конечный код выглядит примерно так: LD SP,addr ;SP=sprite_adr POP AF ;Ч POP BC ; и POP DE ; т POP HL ; а POP IX ; е POP IY ; м EX AF,AF' ; с EXX ; п POP AF ; р POP BC ; а POP DE ; й POP HL ; т LD (SP_1+1),SP ; Сохраняем SP LD SP,addr ;SP=screen_adr PUSH HL ;В PUSH DE ; ы PUSH BC ; в PUSH AF ; о EX AF,AF' ; д EXX ; и PUSH IY ; м с PUSH IX ; п PUSH HL ; р PUSH DE ; а PUSH BC ; й PUSH AF ; т LD (SP_2+1),SP ;сохраняем SP SP_1 LD SP,0000 ;SP=sprite_adr ............ ;снова чтение ............ ;данных SP_2 LD SP,0000 ;SP=screen_adr ............ ;снова вывод и т.д. Итого получаем 302/10=30.2 тактов на два байта! Как видно, разница ощутима, особенно при выводе больших объемов графики. Для дости- жеия максимальной скорости лучше обойтись без всяких циклов, а так и выводить дальше весь спрайт. Теперь расскажу о некоторых полезных приемах, которые могут вам помочь. Нередко, особенно в демках, картинка со- стоит из нескольких повторений одной и той же ее части. При этом, само собой, доста- точно один раз считать эту часть, а затем выкидывать ее на экран нужное число раз. Если вам необходимо вывести спрайт с мас- кой, то часто удобно поступить следующим образом: спрайт хранить в памяти переме- шанным с маской, и считывать одновременно и то, и другое. Пример: LD SP,data_adr ;адрес спрайта LD DE,scr_adr ;адрес экрана POP BC ;B=mask, C=sprite LD A,(DE) AND B ;A AND mask OR C ;A OR sprite LD (DE),A Именно этот способ, слегка модифицирован- ный, применяется для вывода курсора в жур- нале. Курсор хранится в виде 2_байта_дан- ных+2_байта_маски. Перед выводом маска и спрайт сдвигаются на нужное число битов, и полученные _ТРИ_ байта спрайта бросаются на экран. Как видите, все работает без мерцаний и глюков! Да, кстати, все вещи, которые могут нахо- диться в любом месте экрана и при этом еще и двигаться (различные курсоры, прыгающие смайлики и т.п.), необходимо выводить са- мыми первыми, до проигрывания музыки, пе- ресчета координат и т.д. Иначе, даже если у вас все работает отлично, может попасть- ся какой-нибудь тормозной комп, где спрайт начнет дрожать и мерцать. Не забывайте об этом! А засим я на сегодня прощаюсь, если воз- никнут какие-либо вопросы, пожелания или предложения, то вы можете связаться со мной по телефону 54-01-70 (спросить Олега) или же по адресам, приведенным в разделе "От редакции". Bye!!! _______________________________________End
Другие статьи номера:
Похожие статьи:
Презентация - "Bard's Tale Merger Programm" - программа для работы с отгрузками из игры Bard's Tale.
В этот день... 21 ноября