• avatar Shiru
  • 1
На NES всё же сопроцессоров не было, а работа с дополнительным железом через память на NES/SNES просто потому что на семействе 6502 нет портов в принципе. Аппаратные непрограммируемые вычислялки, типа описанной в топике, на приставках и комьпютерах встречались крайне редко, навскидку вспоминается только аппаратный MUL/DIV на SNES, и до какой-то степени DSPx (программируемый, но программу нельзя менять). Более универсальные сопроцессоры делали заметно чаще, и на ZX, можно сказать, тоже был — GS/NeoGS.
  • avatar aa-dav
  • 0
ааааа, ненавижу gamedev.ru в плане поиска — просто редиректит на гугл с site:gamedev.ru и нихрена толком не ищет.
я там просто выкладывал свои сравнения для разных вариантов put_pixel и мне тогда показалось, что табличный метод не имеет решающего преимущества перед сдвигами и масками. и табличный метод именно так и реализовывался — перед таблицами внедрялась директива ассемблера выравнивания на 256 байт.
а, ладно, последние эксперименты с этим можно посмотреть тут: yadi.sk/d/XJzNIt4g3YcMsP но тут уже нет табличного метода.
Пример сотен байтов-килобайтов?
Быстрое рисование отрезка, нешто забыл? Твой же код жрёт больше трёх килобайт даже без таблиц. А уже если радикально оптимизировать под короткие отрезки, как завещал Алоний, то хорошо, если всё в страницу поместится. Вопрос знаю, как раз на днях нашлись мои старые наработки, будет время, доведу до конца:
zx-pk.ru/threads/11661-o-risovanii-pryamykh.html?p=986444&viewfull=1#post986444
Вывод спрайтов может обойтись в сотни лишних байтов вместе с обвязкой.

Объясни, о чем ты, в чем ошибочность, итд
в том, что минимальный размер экрана не означает экономного расходования памяти
  • avatar Raider
  • 0
Это не locate pixel, это locate byte, допустим для вывода спрайта.
Таблица экранных адресов выравнена в памяти на адрес кратный 256 байт и занимает 256+256=512 байт памяти, имея следующую организацию:
первые 256 байт — младшая часть адреса
вторые 256 байт — старшая часть адреса

Из каждых 256 байт важны только первые 192 байта, остальные заполнены нулями и организуют бонусом автоматический «клиппинг», т.к. вместо адреса экрана будет подставлен 0 и запись уйдет в ROM.
  • avatar aa-dav
  • 0
P.P.S.
Ну да, вспомнил, в первую очередь не нравилось как раз то, что надо потратить почти две страницы памяти и плюс еще возня с тремя битами пикселя в полоске существует. И когда я переделал на сдвиги, то время на эффект «снежка» заметно не изменилось. Хм. Ладно, вопрос видимо не такой простой.
  • avatar aa-dav
  • 0
P.S.

Аааа, не туда смотрел. Странно, у меня табличная выборка была в разы более громоздкая. Надо вспомнить точно что там было, но точно помню что мне очень не понравилось…
  • avatar aa-dav
  • 0
ld h, htable; 7
ld l, y; 4
ld a, (hl); 7


Эммм, но что это? У меня процедура locate_pixel в разы много более громоздкая была даже с табличным основанием.
Что такое htable и почему он рассеян по всем страницам памяти?
  • avatar Raider
  • 0
> и с высокой вероятностью занимает уже сотни байтов, если не килобайтов
Пчму? Пример сотен байтов-килобайтов?

> при ошибочном целеполагании
Объясни, о чем ты, в чем ошибочность, итд
не квадратном
down_hl, как раз, занимает всего лишь 4 такта при правильной готовке. И выполняется так с вероятностью 7/8
и с высокой вероятностью занимает уже сотни байтов, если не килобайтов

Это не делает его удобнее или быстрее чем при постолбцовой раскладке
делает значительно неудобнее

но ситуация не так уж и печальна.
для 128k разве что (и то, лучше бы отдать экрану часть этой памяти)

Скажем так, для столь мелкого экрана как 6144 байта это всё же чудесное решение.
при ошибочном целеполагании
  • avatar Raider
  • 2
ld h, htable ; 7
ld l, y      ; 4
ld a, (hl)   ; 7
inc h        ; 4
ld h, (hl)   ; 7
add a, x     ; 4
ld l, a      ; 4

37 тактов и 512 байт памяти

LD BC, port  ; 10
out (c), reg ; 12
in l, (c)    ; 12
inc b        ; 4
out (c), reg ; 12
in h, (c)    ; 12

62 такта, что к следующему порту можно перейти так.

или в случае 8-битых портов
ld a, reg      ; 4
out (port), a  ; 11
in a, (port)   ; 11
ld l, a        ; 4
ld a, reg      ; 4
out (port), a  ; 11
in a, (port)   ; 11
ld h, a        ; 4

60 тактов

Но дело в другом, такое не принято исходя из соображений здравого смысла. Проблемы вычислений адреса — это по-логике проблемы процессора, проблемы даже алгоритма, а не аппаратуры. Такого не было, даже на PC-шных EGA/CGA/VGA видекартах с их чумовейшими битпланами, на амигах/атарях, на консолях или на монструозных arcade game board.
Однако это не значит что данный подход плох или не работает. Работает, и такая идея и меня давно посещала также, и для вычисления адреса, и позже — для выполнения умножения/деления, либо для более генеральных вещей — для общения с «сопроцессором». Подобное весьма активно использовалось на NES/SNES, в дополнительных RISC-микропроцессорах стоящих на картридже игры, только работало не через OUT, а через запись в ячейки памяти и/или DMA.
  • avatar aa-dav
  • 0
«Иными словами, вычислять экранный адрес по двум координатам?»

Не только экранный адрес, но и адрес цвета. Там же просто перемешать биты определенным образом и готово и то и другое за нулевое машинное время — ни складывать ни вычитать не надо. Но есть возня с портами дольше даже, чем перемешивание бит, то… вот как раз и хотелось спросить про это.
  • avatar Raider
  • 1
down_hl, как раз, занимает всего лишь 4 такта при правильной готовке. И выполняется так с вероятностью 7/8, то есть 87.5%
Это не делает его удобнее или быстрее чем при постолбцовой раскладке где столбцы 256 байт, но ситуация не так уж и печальна. Скажем так, для столь мелкого экрана как 6144 байта это всё же чудесное решение.
1) на z80 возня с портами неудобна, медленна и, как следствие, обычно невыгодна
2) даже если был бы небольшой выигрыш, всё равно адрес по координатам объекта (спрайта, конца отрезка) вычисляется однократно, и в % от всего объекта будет уж совсем незначительным
3) не решает основную проблему нелинейной раскладки — медленный и неудобный down_hl, который нужен многократно на весь объект
4) в оригинальной юле, насколько помню, места не осталось уже совсем; добавлять вторую = удорожать комп; а если уж удорожать, то не для такой ерунды, а чего-нибудь намного полезнее (например, автоматического пересчета удобного логического адреса произвольного окна в неудобный физический адрес экрана, не отказываясь от экономии памяти)
  • avatar ShaMAN
  • 0
ну типа того, да.
  • avatar Raider
  • 0
Иными словами, вычислять экранный адрес по двум координатам?
Это не имеет смысла, так как он и так быстро вычисляется по таблице 512 байт, если расположить её в памяти с адреса кратного 256:

ld h, htable ; 7
ld l, y      ; 4
ld a, (hl)   ; 7
inc h        ; 4
ld h, (hl)   ; 7
add a, x     ; 4
ld l, a      ; 4
  • avatar aa-dav
  • 0
Т.е. в принципе сдвигами или таблицей выборки получилось бы быстрее, чем через порты ввода-вывода?
  • avatar ShaMAN
  • 0
*60 тактов
  • avatar ShaMAN
  • 2
а нахрена?
вообще можно конечно прилепить МК какой (УЛА тут и не нужен), который будет слушать порты и плевать ответы. но:
1. это уже будет не совсем спектрум
2. 2 OUT + 3 IN — 48 тактов, это без учета установки регистра C
  • avatar Shiru
  • 2
Другой плюс — можно делать произвольную ширину экрана в столбцах, и код работы с экраном при этом не меняется, всегда остаётся inc/dec l для перехода между пиксельными строками и inc/dec h для перехода между столбцами знакомест. Собственно, если вдруг кто не знает, у Специалиста и Ориона довольно необычное разрешение 384x256, т.е. 48 знакомест в ширину.