Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Флейм > zx+asm


Автор: oleg1973 13.6.2005, 14:42
и так пока там решаетса вопрос о том делат тему или нет вот мои наблюдения на тему:
после комфорта вин/линух с их окошками кодит в самом емуляторе ушербно )
рекомендую кросс компилер sjasm или z80asm при необходимости к ним прикручиваетса IDE

еше нам понадобитца некий софт для переноса скомпиленного бинарника на образ диска TRD
я нашел пару плагинов для тотал командера, работают вполне сносно

ну и естестно нада емулятор, тем у кого реал спека нет )
помучив вчера чтук 10 емулей я остановилса на

EmuZWin v2.6 release 1.6
(С) by Vladimir Kladov, 2003-2005

и

ZX-Emul for Windows v0.31a by Vladimir Yudin aka Lion17
Rostov-on-Don, Russia © 2002-2005

кому нада ссылки пишите или могу сюда кинут )))
в принципе в гуугле за 5 мин исчетса

Автор: Payne 13.6.2005, 20:12
Я думаю, на первых порах можно обойтись эмулем и программой GENS v MONS. Многое еще нужно вспомнить, многому просто научиться.
На крайняк я могу достать "из под дивана" свой Спек, подключить его к ящику (а то монитор че-то кашлял, когда я его последний раз включал smile ), к магнитофону, а потом юзать тот же Real Spectrum, чтобы делать TAP-images.

Цитата(oleg1973 @ 13.6.2005, 14:42)
EmuZWin v2.6 release 1.6
(С) by Vladimir Kladov, 2003-2005

и

ZX-Emul for Windows v0.31a by Vladimir Yudin aka Lion17
Rostov-on-Don, Russia © 2002-2005

А почему не поюзать ZX-32?

Автор: oleg1973 13.6.2005, 21:54
а zx32 поддерживает мультиколор general sound и прочие прибамбасы?

Автор: Mayk 13.6.2005, 22:45
Давайте вспоминать команды. Переписываю их из "Ассемблер Z-80" под редакцие Y. TAHT - это единственная кника по асму на Z80, которуя я прочитал от корки до корки(тут вместо "8-битовый регистр" говорится "рука", вместо "16-битовый" - "нога").
Отмечу жирным команды, которые я не помню в той или иной мере.
(обозначения: r8 - A,B,C,D,E,H,L, r16 - BC, DE, HL, IX, IY, n8 - любое 8-битное число, cn - условие, значение одного из флагов, n16 - любое 16-битное число)

ADC A, r8 - сложение с учетом переполнения
ADC A, n8 - сложение с учетом переполнения
ADC A, (HL)/(IX+n8)/(IY+n8) - сложение с учетом переполнения
ADC HL, BC/DE/HL/SP - сложение с учетом переполнения
ADD A, r8 - сложение
ADD A, n8 - сложение
ADD A, (HL)/(IX+n8)/(IY+n8) - сложение
ADD HL, BC/DE/HL/SP - сложение
ADD IX, BC/DE/IX/SP - сложение
ADD IY, BC/DE/IY/SP - сложение
AND r8/n8/(HL)/(IX+n8)/(IY+n8) - логическое И для аккумулятора.
BIT - проверка включен ли n-ный бит
CALL addr - вызов процедуры
CALL cond, addr - вызов процедуры по условию
CCF - инвертирование значения флага переноса CY (Payne)
CP r8 - сравнить аккумулятор с регистром
CP n8 - сравнить с аккумулятор с числом
CPD - сравнение аккумулятора и ячейки с декрементом
CPDR - сравнение аккумулятора и ячейки с декрементом BC раз
CPI - сравнение аккумулятора и ячейки с инкрементом
CPIR - сравнение аккумулятора и ячейки с инкрементом BC раз
CPL - команда, инвертирующая все биты значения из регистра-аккумулятора (Payne)
DAA - BCD коррекция после сложение(19h+01h=1ah -- daa --> 20h)
DEC (HL/IX+n/IY+n) - вычесть единицу из указанной ячейки памяти
DEC r8/r16/SP - вычесть единицу из указанного регистра
DI - запретить прерывания
DJNZ n8 - уменьшает B, сравнивает его с нулем, если не ноль - прыжок
EI - разрешить прерывания
EX (SP), HL/IX/IY - обменять значения верхушки стека с указаным регистром
EX AF, AF' - обменять значения AF и альтернативного AF'
EX DE, HL - обменять значения DE и HL
EXX - обменять регистры и альтернативные 'регистры
HALT - ничего не делать до прерывания
IM 0/1/2 - режим прерывания.
IN r8, ( C ) - принять байт из порта, записанного в C
IN A, n8 - принять байт из порта под номером n8
INC (HL/IX+n8/IY+n8) - прибавить единицу к указанной ячейке памяти
INC r8/r16/SP - увеличить регистр на 1
IND - ввод байта из порта в ячейку памяти с декрементом (Payne)
INDR - ввод массива значений из портов в память с декрементом
INI -ввод байта из порта в ячейку памяти с инкрементом (Payne)
INIR - ввод массива значений из портов в память с инкрементом (Payne)
JP (HL/IX/IY) - Переход на адрес, который берется из указанного регистра
JP n16 - переход на указанный адрес
JP cn, n16 - переход на указанный адрес в случае выполнения условия
JR n8 - переход относительно текущего адреса
JR cn,n8 - переход относительно текущего адреса
LD (n16), A/r16/SP - загрузить в ячейку указанный регистр
LD (BC), A - загрузить в ячейку BC аккумулятор
LD (DE), A - загрузить в ячейку DE аккумулятор
LD (HL), r8 - загрузить в ячейку HL указанный регистр
LD (IX+n8/IY+n8), - загрузить в ячейку, номер которой r16 +n8, указанный регистр
LD r8,r8 - загрузить в один регситр содержимое другого
LD r16, r16 - загрузить в один регситр содержимое другого
LD r8,n8 - загрузить в регистр число
LD r16, n16 - загрузить в регистр число
LD r8, (HL/IX+n8/IY+n8) - загрузить в регистр ячейку памяти
LD r8, (n16) - загрузить в регистр ячейку памяти
LD r16, (n16) - загрузить в регистр ячейку памяти
LD A, R - загрузить в аккамулятор регситр сохранения памяти R
LD A, I - загрузить в аккамулятор регситр прерывания I
LD I,A - загрузить в регситр прерывания I аккамулятор (DENNN)
LD SP, (n16) - установить SP из ячейки памяти
LD SP, n16 - установить SP на ячейки памяти
LD SP, IX/IY/HL - загрузить в SP указанный регистр
LDD - byte(DE)=byte(HL), BC=BC-1, DE=DE-1, HL=HL-1
LDI - byte(DE)=byte(HL), BC=BC-1, DE=DE+1, HL=HL+1
LDDR - пока BC не ноль повторять byte(DE)=byte(HL), BC=BC-1, DE=DE-1, HL=HL-1
LDIR - пока BC не ноль повторять byte(DE)=byte(HL), BC=BC-1, DE=DE+1, HL=HL+1
NEG - изменить знак аккамулятора (A=-A)
NOP - ничего не делать

... to be continued (ниже)...

Автор: oleg1973 14.6.2005, 00:04
IM 0/1/2
прерывания , вектор как раз в регистр I пишется
при IM 2 (вроде сам тоже не помню) каждые 70000 тактов проц передает управление на код который находится по адресу указаному в регистре I
IM 0 не задействовано

Автор: DENNN 14.6.2005, 09:49
Цитата(oleg1973 @ 14.6.2005, 00:04)
IM 0 не задействовано

IM0 кажись использовалось в микродрайвах. Там прерывание бросается по адресу, указанному в потоке. Потоки размещаются в памяти между системными переменными и областью, отведенной под код бейсика.
IM 1 - стандартный режим прерываний.
IM 2 - расширенный режим. Есть два вида конструкций. В первом виде при наступлении прерывания код следующей выполняемой инструкции помещается в стек и управление передается по адресу, записанному в ячейке по адресу, в котором старший бит равен регистру I, а младший бит равен #FF. Такая схема описывается во всей литературе, которую я видел.
Но есть еще другая конструкция железа (видимо пришедшая со времен первого спеки). В ней младший байт равен не #FF, а берется значение с шины данных, т.е. случайное число, но кратное двум (почему, сейчас не помню).
За отрисовку экрана отвечает отдельная микросхема, называемая ULA. В момент начала формирования верхней строки генерируется прерывание. На шине данных в этот момент информация, которая формирует изображение на мониторе. Именно отсюда и берется этот второй случайный байт. В более поздних моделях это было "пофиксено" и байт стал равняться всегда #FF


Цитата(Mayk @ 13.6.2005, 22:45)
LD A, I - загрузить в аккамулятор регситр I (что есть I?)

Верно. Причем вроде д.б. обратная операция LD I,A

Цитата(Mayk @ 13.6.2005, 22:45)
INI

Вроде прерывание генерировать должно было. Но на спекки не использовалась (за исключением интерфейса с микродрайвом).

Команды LDDR и LDIR примечательны тем, что на самом деле они работают не как цикл, а перемещают блок памяти за 5 тактов (могу сейчас ошибаться). Блоки источника и приемника могут перекрываться, отсюда и две вариации команды.

Сейчас многое уже не помню, но если интересно, могу в сети инфу найти и освежить память smile

Автор: Mayk 14.6.2005, 10:26
Цитата(oleg1973 @ 14.6.2005, 00:04)
код который находится по адресу указаному в регистре I

Вот http://www.nvg.ntnu.no/sinclair/faq/tech_z80.html нашел:
Цитата

In IM 1, the processor simply executes an RST #38 instruction if an interrupt is requested.


Цитата(DENNN @ 14.6.2005, 09:49)

в котором старший бит равен регистру I, а младший бит равен #FF. Такая схема описывается во всей литературе, которую я видел.

Про IM 2 там сказано следующее
Цитата

The other mode that is commonly used on the Spectrum is IM 2. If an interrupt is requested, the processor first builds a 16 bit address by combining the I register (as the high byte) with whatever the interrupting device places on the data bus. The processor then fetches the 16-bit address at this interrupt table entry, and finally calls the subroutine at that address.--- skip ---
The normal Spectrum contains no hardware to place a byte on the bus, and the bus will therefore always read FF (because the ULA also doesn't read the screen if it generates an interrupt), so the resulting index address is 256*I+255


Цитата(DENNN @ 14.6.2005, 09:49)

Верно. Причем вроде д.б. обратная операция LD I,A

Да, есть такая.
Цитата(DENNN @ 14.6.2005, 09:49)

могу в сети инфу найти и освежить память

Давай.

Автор: Payne 14.6.2005, 10:43
Цитата(Mayk @ 13.6.2005, 22:45)
что есть I?

I - это регистр вектора прерываниий Z80.

Цитата(Mayk @ 13.6.2005, 22:45)
CPL - ???

CPL - команда, инвертирующая все биты значения из регистра-аккумулятора, то есть A -> !A. После выполнения операции устанавливаются флаги переноса и отрицательного результата.

Цитата(Mayk @ 13.6.2005, 22:45)
IND - ??? Hex : ED AA
INCR - ??? Hex : ED BA
INI - ??? Hex: ED A2
INIR - ??

IND - ввод байта из порта в ячейку памяти с декрементом;
INCR - ?
INI - ввод байта из порта в ячейку памяти с инкрементом;
INIR - ввод массива значений из портов в память с инкрементом.

Автор: Mayk 14.6.2005, 11:12
Цитата(Mayk @ 13.6.2005, 22:45)
CPF - ??? - сравнить с флагом? (команда 3F)

Опечатка в книге. Следует читать CCF.
CCF - сбросить флаг переноса C

Цитата(Mayk @ 13.6.2005, 22:45)
CPD - ??? - Hex: ED A9

Опытным путем - сравнение аккамулятора A и (HL) с декрементом HL, BC
По аналогии:
CPI - Опытным путем - сравнение аккамулятора A и (HL) с декрементом BC, инкрементом HL

CPIR - Выполнить команду CPI BC кол-во раз
CPDR - Выполнить команду CPD BC кол-во раз

INCR - Двойная опечатка в книге(ну и мрак). Похоже следует читать
INDR, Opcode: ED 8A
По аналогии - ввод массива значений из портов в память с декрементом.
Похоже, половину команд вспомнили.

Автор: Payne 14.6.2005, 12:57
Цитата(Mayk @ 14.6.2005, 11:12)
CCF - сбросить флаг переноса C

В моей книге дано следующее описание: CCF - инвертирование значения флага переноса CY. При этом состояние флага переноса меняется на противоположное, флаг отрицательного результата N сбрасывается, состояние флага H не определено.

Цитата(Mayk @ 14.6.2005, 11:12)
Похоже, половину команд вспомнили.

Может, нужно еще вспомнить регистры процессора Z80?
Предлагаю сделать это.

Регистры данных и аккумулятор
Микропроцессор Z80 работает с двумя наборами регистров - основным и альтернативным. Оба набора состоят из семи 8-разрядных регистров данных и флагового регистра. Регистры основного набора обозначаются буквами A, B, C, D, E, H, L и F (флаговый). Регистры альтернативного набора соответственно - A', B', C', D', E', H', L' и F'. С помощью специальных команд можно переключать работу процессора с одного набора регистров на другой. Но определить, какой из наборов активен в данный момент, невозможно.
Для выполнения многих команд обрабатываемые данные должны быть занесены в специальный регистр - аккумулятор A.
Команды, обрабатывающие 16-разрядные числа, используют пары регистров в следующих сочетаниях: BC, DE, HL, AF и, соответственно, BC', DE', HL', AF'. При этом в регистры B, D, H, A, B', D', H', A' записывается старший байт числа, а в C, E, L, F, C', E', L', F' - младший. Спаренные регистры, например, можно использовать для хранения адресов ячеек памяти.

Счетчик команд
Выполняя очередную команду, процессор должен знать, откуда ему взять следующую. За этим следит 16-разрядный регистр счетчика команд PC. В PC записывается адрес команды, которая должна выполниться после текущей.

Индексные регистры
Существует возможность обращаться к ячейкам памяти, указывая смещение их адреса относительно содержимого 16-разрядных индексных регистров IX и IY. Смещение может быть задано числом в пределах -128...+127.

Указатель стека
16-разрядный регистр указателя стека SP содержит адрес вершины стека. Здесь, думаю, все понятно, поскольку стек в Z80 работает по тому же принципу, что и в x86/Pentium. То есть так же растет в сторону уменьшения адресов и при каждой записи или чтении адрес вершины стека меняется на 2.

Регистр флагов
Флагом называется отдельный бит регистра флагов F. Значимыми являются 6 из 8 битов флагового регистра:
- бит 0. CY (carry flag) - флаг переноса;
- бит 1. N (negative) - флаг отрицательного результата;
- бит 2. P/V (parity/overflow) - флаг четности/переполнения;
- бит 4. H (half-carry) - флаг вспомогательного переноса;
- бит 6. Z (zero) - флаг нуля;
- бит 7. S (sing) - флаг вычитания.

Автор: DENNN 14.6.2005, 13:26
Цитата(Payne @ 14.6.2005, 12:57)
обращаться к ячейкам памяти, указывая смещение их адреса относительно содержимого 16-разрядных индексных регистров IX и IY.

Анналогичные операции выполняются с парой регистров HL.

Автор: oleg1973 14.6.2005, 13:35
ну что все вспомнили? )
ldir силная чтука на х86 ее нехватает )
но тока она не за 5 тактов перебрасывает там скокото тактов на байт
факт что перерисовка экрана с ldir вроде как не получается, не укладываетса в 70000 тактов что приводит к мерцанию
поэтому все вымучивауют свои варианты обновления экрана

Автор: Mayk 14.6.2005, 15:42
Цитата(Payne @ 14.6.2005, 12:57)
CCF - инвертирование значения флага переноса CY

Точно!


Цитата(oleg1973 @ 14.6.2005, 13:35)
ну что все вспомнили? )

Нее, у нас еще половина команд осталась ;)

Итак (нашел файлик со списком команд и их кратким описанием. Нет опечтакам!):

OR r8/n8/(HL)/(IX+n8)/(IY+n8) - логическое или для аккумулятора и операнда
OUT (n8), A - вывод аккумулятора в порт n8
OUT ( C ), r8 - вывод байта в порт
OUTD - вывод байта в порт с декрементом
OTDR - делать OUTD пока b не 0
OUTI - вывод байта в порт с инкрементом
OTIR - делать OUTI пока b не 0
POP r16/AF - восстановить из стека 16-битный регистр
PUSH r16/AF - поместить в стек 16-битный регистр
RES 0-7, r - сбросить указанный бит в указанном регистре
RES 0-7, (HL)/(IX+n8)/(IY+n8) - сбросить указанный бит в ячейки памяти
RET - возврат
RET cn - возврат при условии
RETI - возврат из прерывания
RETN - возврат из немаскируемого прерывания
RLA - ну и куда девается крайний левый(кстати, это который 0x80?) бит?
RL r8 - повороты я не помню
RLCA - вот это кажется крайний бит кидает в другой крайний - ???
RLC r8 - ???
RLC (HL)/(IX+n8)/(IY+n8) - ???
RLD - ???
RRA - ???
RR r8 -???
RRCA - ???
RRC r8 - ???
RRC (HL)/(IX+n8)/(IY+n8) - ???
RRD - ???
RST 0/0x08/0x10/0x18/0x20/0x28/0x30/0x38 - аналогично CALL 0/../0x38, но в одну команду
SBC r8 - вычесть из аккумулятора r8 с учетом флага переноса
SBC A, n8 - вычесть из аккумулятора n8 с учетом флага переноса
SBC (HL) - вычесть из аккумулятора ячейку памяти с учетом флага переноса
SBC A, (IX+n8)/(IY+n8) - вычесть из аккумулятора ячейку памяти с учетом флага переноса
SCF - установить флаг переноса
SET 0-7, r8/(HL)/(IX+n8)/(IY+n8) - установить бит в ячейке памяти
SLA r8 - сдвиг бит регстра влево (умножение на 2)
SLA (HL)/(IX+n8)/(IY+n8) - сдвиг бит влево в ячейке
SRA r8 - сдвиг бит регстра вправо (деление на 2)
SRA (HL)/(IX+n8)/(IY+n8) - сдвиг бит вправо в ячейке
SLL r8 - ???
SLL (HL)/(IX+n)/(IY+n) - ???
SRL r8 - ???
SRL (HL)/(IX+n)/(IY+n) - ???
SUB r8 - вычесть регистр из аккумулятора
SUB n8 - вычесть n8 из аккумулятора
SUB (HL)/(IX+n)/(IY+n) - вычесть ячейку памяти из аккумулятора
XOR r8 - логическое исключающее или для аккумулятора и r8
XOR n8 - логическое исключающее или для аккумулятора и n8
XOR (HL)/(IX+n)/(IY+n) - логическое исключающее или для аккумулятора и ячейки памяти


Надо еще вспомнить устройство экрана, ввод информации с клавиатуры, работу с памятью >48K, работу с TRDOS.

Автор: oleg1973 14.6.2005, 15:50
Цитата
RLA - ну и куда девается крайний левый(кстати, это который 0x80?) бит?
а почему он должен куда то деватся? помоему это крутит акумулятор и все
а команды типа RLC. делают тоже самое но с установкой влага С в зависимости от состояния бита (вроде так )

Автор: Mayk 14.6.2005, 15:57
Цитата(oleg1973 @ 14.6.2005, 15:50)
а почему он должен куда то деватся?

Он может попасть в C и/или в другой крайний бит или вообще исчезнуть.
То есть RLCшники ставят флаг C в крайний левый бит, крутят байт, на место крайнего правого бита ставят C(он же левый бит до RLC)?


Автор: DENNN 14.6.2005, 16:57
Цитата(Mayk @ 14.6.2005, 15:42)
Надо еще вспомнить устройство экрана,

Область памяти размером в 8К. Первый байт по адресу 16384. В высоту 24 знакоместа (каждое знакоместо 8x8 пикселей, цвет чернил и фона задается одним байтом). Ширину экрана не помню, надо в интернете поискать. Область видеопамяти разбита на 4 части - три под пикселы (каждая высотой в 64 пиксела), одна под цвет.
Цитата(Mayk @ 14.6.2005, 15:42)
работу с памятью >48K,

через порт. Кажется #7FFD. Записью значения в него переключается номер отображаемой страницы.

Цитата(Mayk @ 14.6.2005, 15:42)
работу с TRDOS.

Передача управления на байт по адресу 15616 приводит к переходу в оболочку tr-dos, по адресу 15619 можно осуществлять выполнение отдельных команд.

Автор: oleg1973 14.6.2005, 17:24
ну все память освежили ) пора тетрис или питона начинать делать имхо )

Автор: Payne 16.6.2005, 10:49
Цитата(oleg1973 @ 14.6.2005, 17:24)
ну все память освежили ) пора тетрис или питона начинать делать имхо )

Да, что-то когда участники услышали эту фразу, сразу решили по тихому скрыться в теме ZX+Games smile . Имхо если говорить обо мне, то рановато еще писать гаму на zx-asm'е - нужно еще дочитать книгу "Как написать игру на Ассемблере для ZX Spectrum". Дочитаю, вернусь в этот топик и мы с вами напишем то, о чем вы говорите.

Автор: Mayk 16.6.2005, 13:01
Давайте лучше подробнее вспомним устройство графики и ввод с клавиатуры!
Подробней вот отсюда:
Цитата(DENNN @ 14.6.2005, 16:57)
Область видеопамяти разбита на 4 части


На установление всего опытным путём времени мало.
Ну а пока, может на басике что-нибудь напишем? Спеки - не PC. На спеки на басике писать совсем не стыдно smile

Payne
Книгу можно найти где-нибудь в электронном варианте?

Автор: oleg1973 16.6.2005, 15:55
да че там вспоминать?
клава там с какогото порта читается, экран тоже не проблема )

Автор: Mayk 16.6.2005, 18:26
oleg1973
На четыре части можно разделить многими способами. Я хочу такой справки:
#4000-XXXX - экран прорисовывается так-то так-то и так-то
XXXX+1-YYYY - так-то и вот так-то
YYYY+1-#5800 - вот так и никак иначе
#5800-ZZZZ - аттрибуты. Они представлены так-то и так-то.

Цитата(oleg1973 @ 16.6.2005, 15:55)
клава там с какогото порта читается

#0FE smile
Там кажется надо послать бит, идентифицирующий полуряд клавиатуры,
а потом считать оттуда какая клавиша полуряда нажата

Автор: Payne 16.6.2005, 18:36
Цитата(Mayk @ 16.6.2005, 13:01)
Давайте лучше подробнее вспомним устройство графики

Насчет графики.
С адреса 16384 (#4000) начинается видеопамять. Она имеет размер 6 Кб. Далее, с адреса 22528 (#5800) идет область атрибутов экрана (768 байт).
Размер экрана ZX Spectrum составляет 256x192. Стандартные знакоместа имеют размер 8x8 пикселей. Следовательно, на экран можно вывести 24 строки по 32 знакоместа в каждой.
При выводе изображения на экран каждый байт экранной области определяет состояние 8 расположенных горизонтально одна за другой точек (бит 7 соответствует левой точке, бит 0 - правой). Байты, соответствующие строкам экрана, расположены в памяти не последовательно. Первые 32 байта экранной области задают слева направо верхнюю строку, следующие 32 байта - 9-ю сверху, следующие - 17-ю и далее через 8 строк вплоть до 57-й. Затем расположены байты, соответствующие 2-й, 10-й и т.д. до 58-й. Так задается треть экрана. Аналогично задаются средняя и нижняя трети экрана. Я так понимаю, что из-за этого и получается разбивка видеопамяти на 4 части - под пикселы и цвет.

Цитата(Mayk @ 16.6.2005, 13:01)
Книгу можно найти где-нибудь в электронном варианте?

Книги ищи http://zx-games.narod.ru/zxbooks.htm.

Автор: oleg1973 16.6.2005, 19:49
на виртуал тр-дос книги есть

Автор: Mayk 17.6.2005, 18:35
И все молчат. smile
oleg1973 прально сказал, давайте делать питончика.
Итак, давайте думать как его реализовать.
Давайте рассмотрим возможные алгоритмы перемещения.

1) Связной список координат
На си это так: struct snake_node{ snake_node* prev; snake_node* next; int x,y; };
Перемещение делается элементарно - вычисляется координаты головы, отцепляется хвост, хвостовой элемент ставится в голову. Стоимость выполнения О(1).
Недостатки - расход памяти(даже если сделать список с одинарными связями)
Достоинства - легкость реализации(в си, на асме я линкед листы давно не делал)

2) Массив координат
struct node{int x,y};
node[MAX_SNAKE_LEN]
int head_offset; - node[head_offset] -здесь начинается голова змия
int len_offset; - node[head_offset+len] - здесь хвост змия

Стоимость движения в среднем O(1):
node[head_offset-1].x=new_head_x
node[head_offset-1].y=new_head_y
head_offset--;
Недостатки:
В худшем случае(head_offset=0) потребуется переместить всего змия в конец массива... LDIR, как мы выяснили, делает это за константное время => в худшем случае время тоже О(1)
Длина змеи ограничена MAX_SNAKE_LEN элементами.

3) Массив направлений
typedef enum{North, South, West, East};
int tail_x, tail_y;
int directions[]
directions[] показывает в какую сторону двигаться от хвоста к голове. Используя LDIR добиваемся все того же О(1):
Head Direction: North
int directions[] = {East, East} (сейчас змея вот так стоит >>> )
Пихаем в direction[2]=North (>>>^), сдвигаем змею: >>^
Достоинства: Жрет мало памяти
Недостатки: LDIR почти каждый ход(если змея не растет). Нужно высчитывать координаты змеи.

4) Массив сильно сжатый
Модифицировать 3ий алгоритм. Направления задавать не 8ью битами, а двумя:
00 - двигаем на север
01 - на запад
10 - на восток
11 - на юг
Достоинства - ест ОЧЕНЬ мало памяти
Недостатки - LDIR использовать уже нельзя. Следовательно, при каждом движении потребуется около n/8+1 одних только сдвигов

5) ????


PS.Блин, narod.ru какой-то тормознутый, чтобы файлы качать.

Автор: oleg1973 19.6.2005, 15:24
массив 192*256*2 бита
там рисуем питона битами
храним координату ЖО питона, ну ее удалять нада при движении ))
ну и нужна процедура вывода бит-массива на экран
типа 0 - пусто
1- спрайт сегмента питона
2- типа яблоко которое сожрать нада чтоб вырости
и так далее )
имхо отрисовку нада делать в 128 режиме на 2х экранах (мыж в 21 веке все таки) )


Автор: Mayk 19.6.2005, 18:31
Цитата(oleg1973 @ 19.6.2005, 15:24)
массив 192*256*2 бита

Это же размеры экрана? А как тогда отличить яблоко от змия? Давай делать tile 4x4 бита. Таким образом размер массива: (192/4)*(256/4)*2 бита = (68)*(64)*2 бита=4352/4 = 1088 байт. Кстати, нужен еще статус бар.
Шрифты стандартные не юзаем. Используем те же 4х4 бита. А массив теперь становится 67*64*1/4=1072 байта. Запомним это число.

Цитата(oleg1973 @ 19.6.2005, 15:24)

там рисуем питона битами
храним координату ЖО питона, ну ее удалять нада при движении ))

Да, точно. Так и сделаем!
+2 байта = 1074 байт.

Цитата(oleg1973 @ 19.6.2005, 15:24)

ну и нужна процедура вывода бит-массива на экран
типа 0 - пусто
1- спрайт сегмента питона
2- типа яблоко которое сожрать нада чтоб вырости

Лучше все же хранить в массиве направление к голове - тогда потребуются еще 2 байта на координаты яблока, но питон будет рисоваться очень быстро.
1074+2=1076 байт

Цитата(oleg1973 @ 19.6.2005, 15:24)

и так далее )
имхо отрисовку нада делать в 128 режиме на 2х экранах (мыж в 21 веке все таки) )

Не стоит имхо. Памяти столько не расходуем smile
Да и изменения на экране минимальны. Вот начнем писать стратегию
smile

Теперь надо придумать как изображать тайлы. Для змия и яблока потребуются 16 байт. Запихнем их в область шрифтов для экономии места smile
Также не забудем про шрифт. Сгруппируем все в 32 байта. И заменим редко используемые символы в шрифте.
Наброски тайлов:
Код

 01234567  01234567 
0####.AA. 0.WWWEEE. 
1####AAAA 1WW.WE.EE 
2####AAAA 2WW.WE.EE 
3####.AA. 3.WWWEEE. 
4.0..1... 4.NN.SSSS 
50.0.1... 5NNNNS..S 
60.0.1... 6N..NSSSS 
7.0..1... 7NNNN.SS.

 01234567  01234567 
0222.333. 0.66.777. 
1..2..3.. 16.....7. 
222....3. 2666..7.. 
3222.33.. 3.6...7..
44.4.555. 4.8...9..
5444.55.. 5888.999. 
6..4...5. 6888...9.
7..4.55.. 7.8..99..

Расшифровка:
# - тело змия
0...9 - цифра
N - голова направлена на сервер(хвост направлен на юг)
W - голова направлена на запад(хвост направлен на восток)
S - голова на юг
E - голова на восток
Ну для хвоста можно еще 8 байт использовать

Нда, шрифты надо фиксить, бо уродство.

Ладно, хватит теории. Пора переходить к практике, но не сегодня.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)